这题可真是又让我找到了八数码的感觉。。。哈哈。
首先,第一次见题,没有思路,第二次看题,感觉是搜索,就这样写下来了。
这题我几乎是一个点一个点改对的(至于为什么是这样,后面给你看一个神奇的东西),让我发现了许多搜索上的问题。思路非常简
单:搜索出每一种可能的配对方式,然后从每一个点出发
一遍,模拟走的过程,如果到死循环里面就答案加一,那个模拟走的过程话说我敲的还是很爽的,这题难在对配对序列的搜索和配对状态重
复的剪枝上面。
记得配对序列的搜索我敲了5、6个版本,发现AC之后一个都没有用上,但是在这个过程中,你脑袋里面模拟那个搜索的过程的确是很爽
啊,确定了搜索序列的方法之后,就分别对每一个序列执行模拟走的操作,但是,这是一个严重的问题出现了,大量的重叠状态,导致所有
N = 12的数据严重超时,让人更加不理解的是,USACO上原题还有小于12的数呢,但是COGS上的数据好像全部都是12,坑了。但是,剪
枝的方法十分的妙,什么,单调。我给出一个不重复的序列作为说明:
当N等于6时,所有可能的序列如下:
12 34 56 | 12 35 46 | 12 36 45 |
13 24 56 | 13 25 46 | 13 26 45 |
14 23 56 | 14 25 36 | 14 26 35 |
15 23 46 | 15 24 36 | 15 26 34 |
16 24 35 | 16 23 45 | 16 25 34 |
我们可能清楚的发现,如果你的搜索顺序对的话,那么有一个神奇而又能让你通过测试的性质,就是这个序列无论什么样子,他的奇数位上
的数字都是单调递增的,正是因为这个东西,让我剪掉了数量非常大的无用状态。
至于怎么体现这句话,关键地方说完了,直接贴代码,自己看吧。。。有许多大神0.0几秒就过了,不能理解,我的0.6几秒,这效率,天
差地
别啊,,,自愧不如。。。。。
Code:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
using namespace std; int N;
int Ans = 0;
bool vi[15];
bool a[15][15];
int que[15];
struct data{
int x,y;
}G[15]; int T[30];
int tot = 0; void dfs(int,int,int);
bool cmp(data,data);
bool judge();
bool go(int,int);
void outandin(); int main(){
freopen("wormhole.in","r",stdin);
freopen("wormhole.out","w",stdout);
scanf("%d",&N);
for(int i = 1;i <= N;++ i){
scanf("%d%d",&G[i].x,&G[i].y);
T[++ tot] = G[i].x;
T[++ tot] = G[i].y;
}
outandin();
sort(G+1,G+N+1,cmp); for(int i = 2;i <= N;++ i){
dfs(1,i,2);
}
printf("%d\n",Ans);
return 0;
} void dfs(int now,int next,int depth){
vi[now] = vi[next] = true;
que[depth] = now;que[depth+1] = next;
if(depth == N && N%2==0){
if(judge())
++ Ans;
return;
}
else if(depth == N-1 && N%2 == 1){
if(judge())
++ Ans;
return;
} for(int i = 1;i <= N;++ i){
if(!vi[i] && i > now){//这括号里面很神奇的一句。。。i > now 剪枝的神器。。
for(int j = 1;j <= N;++ j){
if(!vi[j] && j != i && j > i){
dfs(i,j,depth+2);
vi[j] = false;
}
}
vi[i] = false;
}
}
vi[now] = vi[next] = false;
} bool cmp(data a,data b){
if(a.x == b.x)
return a.y < b.y;
return a.x < b.x;
} bool judge(){
for(int i = 2;i <= (N&1?N:N+1);++ i)
if(go(que[i],i))
return true;
return false;
} bool go(int now,int pos){
bool v[15];
memset(v,false,sizeof v); while(1){
if(v[now])
return true;
v[now] = true;
pos = ((pos&1) ? (pos-1):(pos+1));
bool flag = false;
for(int i = 1;i <= N;++ i){
int n = que[pos];
if(i != n && G[i].x > G[n].x && G[i].y == G[n].y){
for(int j = 2;j <= (N&1?N:N+1);++ j){
if(que[j] == i){
now = que[j];
pos = j;
flag = true;
break;
}
}
}
if(flag)
break;
}
if(!flag)
return false;
}
} map <int,int> pos;
map <int,bool> fla;
void outandin(){
int no = 0;
for(int i = 1;i <= tot;++ i){
if(!fla[T[i]]){
fla[T[i]] = true;
pos[T[i]] = ++ no;
}
}
for(int i = 1;i <= N;++ i){
G[i].x = pos[G[i].x];
G[i].y = pos[G[i].y];
}
} 如果你不剪枝,但是时间又特别特别长的话(也就是没有超时这种东西),你的输出就要这样写:
if(N > 11)
printf("%d\n",Ans/120);
else if(N > 9)
printf("%d\n",Ans/24);
else if(N > 7)
printf("%d\n",Ans/6);
else if(N > 5)
printf("%d\n",Ans/2);
else
printf("%d\n",Ans);
正是这个让我一个点一个点的过,也是这个让我发现了大量的重复状态,由那个/120你就知道重复状态有多么可怕了。。。。。
总之,模拟走的过程练码力,搜索的过程练搜索。。一道非常不错的题目。。。

USACO 1.3... 虫洞 解题报告(搜索+强大剪枝+模拟)的更多相关文章

  1. USACO Section1.3 Wormholes 解题报告

    wormhole解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------- ...

  2. USACO Section1.2 Transformations 解题报告

    transform解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------ ...

  3. USACO 1.4 ariprog 解题报告

    这是继虫洞之后又让我为难的一个 剪枝题目,无论如何,做的再快,也只能过6个点,最后三个点也TLE.后来参考了一下标答,大概思路是这样的. 朴素算法就不多说了,枚举a,b然后判断就行,网上说这样优化到位 ...

  4. USACO 6.3 章节 你对搜索和剪枝一无所知QAQ

    emmm........很久很久以前 把6.2过了 所以emmmmmm 直接跳过 ,从6.1到6.3吧 Fence Rails 题目大意 N<=50个数A1,A2... 1023个数,每个数数值 ...

  5. USACO Section1.4 Mother's Milk 解题报告

    milk3解题报告 —— icedream61 博客园(转载请注明出处)---------------------------------------------------------------- ...

  6. USACO Section2.2 Preface Numbering 解题报告 【icedream61】

    preface解题报告----------------------------------------------------------------------------------------- ...

  7. USACO Section2.1 Hamming Codes 解题报告 【icedream61】

    hamming解题报告----------------------------------------------------------------------------------------- ...

  8. USACO Section2.1 Healthy Holsteins 解题报告 【icedream61】

    holstein解题报告 --------------------------------------------------------------------------------------- ...

  9. USACO Section2.1 The Castle 解题报告

    castle解题报告 —— icedream61 博客园(转载请注明出处)--------------------------------------------------------------- ...

随机推荐

  1. SQL Server事务的存储过程

    在酒店管理系统开发中,我们会创建房间表和房间类型表(房型表)这两个表,如下图所示: 房型表:RoomType 房间表:Room 首先这两个表的关系:Room是从表,RoomType是主表,两表有主外键 ...

  2. .Net Memory -- GC基本知识

    参考资料: http://blogs.msdn.com/b/tess/archive/2008/04/17/how-does-the-gc-work-and-what-are-the-sizes-of ...

  3. C# socket网络编程 基于TCP协议

    socket 服务器端: 1.创建socket Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ...

  4. java基础知识4

    58.线程的基本概念.线程的基本状态以及状态之间的关系线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身.Java中的线程有四种状态分别是:运行.就绪.挂 ...

  5. python运维开发(二十三)---tornado框架

    内容目录: 路由系统 模板引擎 cookie 加密cookie 自定义api 自定义session 自定义form表单验证 异步非阻塞 web聊天室实例 路由系统 路由系统其实就是 url 和 类 的 ...

  6. 美国政府关于Google公司2013年度的财务报表红头文件

    请管理员移至新闻版块,谢谢! 来源:http://www.sec.gov/ 财务报表下载↓ 此文仅作参考分析. 10-K 1 goog2013123110-k.htm FORM 10-K   UNIT ...

  7. 关于SQL SERVER 2008 R2发布订阅功能

    实现功能:主服务器维护数据的变更,从服务器需要时同步主服务器的数据. 配置:主从服务器均为SQL SERVER 2008 R2. 实现方法: 预备: 1.主从服务器需建立同一账户名及密码的账户(当时我 ...

  8. ubuntu14.04 安装搜狗输入法

    (1)下载链接 http://pinyin.sogou.com/linux/ (2)清除fcitx $sudo apt-get purge fcitx* (3)使用deb安装工具gdebi,这个工具能 ...

  9. BZOJ 2876 骑行川藏

    http://www.lydsy.com/JudgeOnline/problem.php?id=2876 拉格朗日乘数法:f'+入g'=0,f为函数的导数,g为限制条件的导数. 思路:E=Σki*si ...

  10. TEA加密

    TEA(Tiny Encryption Algorithm)是一种小型的对称加密解密算法,支持128位密码,与BlowFish一样TEA每次只能加密/解密8字节数据.TEA特点是速度快.效率高,实现也 ...