这题可真是又让我找到了八数码的感觉。。。哈哈。首先,第一次见题,没有思路,第二次看题,感觉是搜索,就这样写下来了。这题我几乎是一个点一个点改对的(至于为什么是这样,后面给你看一个神奇的东西),让我发现了许多搜索上的问题。思路非常简
单:搜索出每一种可能的配对方式,然后从每一个点出发
一遍,模拟走的过程,如果到死循环里面就答案加一,那个模拟走的过程话说我敲的还是很爽的,这题难在对配对序列的搜索和配对状态重
复的剪枝上面。记得配对序列的搜索我敲了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);elseprintf("%d\n",Ans);
正是这个让我一个点一个点的过,也是这个让我发现了大量的重复状态,由那个/120你就知道重复状态有多么可怕了。。。。。
总之,模拟走的过程练码力,搜索的过程练搜索。。一道非常不错的题目。。。

转载于:https://www.cnblogs.com/sxprovence/p/4705070.html

USACO 1.3... 虫洞 解题报告(搜索+强大剪枝+模拟)相关推荐

  1. 细菌(disease)解题报告 - 搜索与回朔

    细菌(2009jxd) Time Limit:1000MS  Memory Limit:65536K Total Submit:3 Accepted:1 Description 近期,农场出现了D ( ...

  2. [USACO Nov08]玩具toys解题报告

    题目 http://cogs.pro/cogs/problem/problem.php?pid=2007 分析 首先,稍有常识的人都会看出,这道题其实就是网络流24题中"餐巾问题" ...

  3. USACO Betsy's Tour 解题报告

    大神做了这道题:https://www.byvoid.com/blog/usaco-544-betsys-tour.解释得非常清楚,我也是按照这种方法做的,即统计"必经点"的个数, ...

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

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

  5. codeforces 解题报告 978A. Remove Duplicates 模拟

    http://codeforces.com/contest/978/problem/A 解题思路: 1.删掉重复的元素,只留下序列中不重复的最右边的元素 2.逆向搜一遍,把第一次遇到的元素入栈 3.依 ...

  6. USACO 3.3.2 Shopping Offers解题报告

    写在前面:因为之前没写的C++的USACO Training的解题报告太多--所以就不写了,要是想要代码可以联系我:xiedong_1993@foxmail.com 这题就是传说中的五维背包,其实写起 ...

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

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

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

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

  9. USACO Section1.3 Combination Lock 解题报告

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

最新文章

  1. vue-router获取url传参
  2. java char字符转编码_一、java基础-数据类型_数据类型转化_字符编码_转义字符
  3. 2016国产开源软件Top100(Q1)
  4. LeetCode872. Leaf-Similar Trees
  5. python二维码生成器制作中报错为oserror_Python生成:OSError:[WinError 193]%1不是有效的Win32应用程序...
  6. 在DataTable和DataView中查找指定记录
  7. 使用jenkins进行Android的持续集成
  8. 在SQL SERVER里面用命令查包含某字段的表
  9. 踩坑合集(1)——虚拟机桥接模式下的连网问题
  10. 干货!电商小白入门电商运营必看
  11. java实现界面化,java实现图形化界面
  12. 简单粗暴,java pdf转word,word转图片,无水印,无大小限制
  13. 360 android系统 流量,360流量卫士 for Android
  14. volatile关键字
  15. pymssql连接sql server报错Unable to connect: Adaptive Server is unavailable
  16. LaTex 数学之运算符
  17. 金融科技大数据产品推荐:金融魔方 ---专业的金融SaaS服务平台
  18. Shopee使用虚拟信用卡绑卡测试购物教程
  19. 【Java学习笔记】1:Java语言基础
  20. 腾讯2019技术岗笔试 猜硬币 众所周知,每一枚硬币都有两面,假定投掷一枚硬币,得到正面和反面的概率是一样的。小Q有一天和好朋友在玩投掷硬币的游戏,他投了n枚硬币,已知至少有p正,q反,求n枚硬币

热门文章

  1. python怎么写文件-来看文件处理Python怎么写?
  2. python爬取百度图片(用于深度学习中数据集的收集)
  3. NameServer的启动
  4. ControlAdvice和ExceptionHandler处理异常的原理与设计
  5. PHP内核介绍及扩展开发指南—高级主题
  6. INSERT IGNORE 与INSERT INTO的区别
  7. 开源企业IM免费企业即时通讯ENTBOOST V2014.177版本号正式公布
  8. 181102 Python环境搭建(安装Sublime Text3)
  9. go语言之行--基础部分
  10. 让你分分钟学会Javascript中的闭包