USACO-Section1.3 Wormholes [搜索]
来源:互联网 发布:外星文明等级 知乎 编辑:程序博客网 时间:2024/06/06 01:15
2017-6-1
题目大意
农夫约翰爱好在周末进行高能物理实验的结果却适得其反,导致农场上产生了N个虫洞(2<=N<=12,n是偶数),每个在农场二维地图的一个不同点。
根据他的计算,约翰知道他的虫洞将形成 N/2 连接配对。例如,如果A和B的虫洞连接成一对,进入虫洞A的任何对象体将从虫洞B出去,朝着同一个方向,而且进入虫洞B的任何对象将同样从虫洞A出去,朝着相同的方向前进。这可能发生相当令人不快的后果。
例如,假设有两个成对的虫洞A(1,1) 和 B(3,1),贝茜从(2,1)开始朝着 +x 方向(右)的位置移动。贝茜将进入虫洞 B(在(3,1)),从A出去(在(1,1)),然后再次进入B,困在一个无限循环中!| … .
| A > B . 贝茜会穿过B,A,
+ … . 然后再次穿过B农夫约翰知道他的农场里每个虫洞的确切位置。虽然他不记得贝茜的当前位置,但是他知道贝茜总是向着 +x 的方向走。请帮助农夫约翰计算不同的虫洞配对(情况),使贝茜可能从不幸的位置开始被困在一个无限循环中。(copy from nocow)
题解
这题分为两个步骤:
一、找出所有的配对情况。
二、判断当前配对是否能构成无限循环。枚举所有的配对情况,可以用dfs+回溯实现。dfs(step)每次搜索,都将匹配一对虫洞,搜索深度最大为n/2。step=n/2时表示已经配对了n/2对,已经找到一种配对情况。我们每次先找到一个未被标记的虫洞s,然后再枚举所有其他的未被标记的虫洞v来与s配对。
判断无限循环,枚举所有可能的开始位置,然后判断经过虫洞的次数之和是否超过了2n。超过2n则说明陷入了循环。
代码
/*ID: zachery1PROG: wormholeLANG: C++*/#include <iostream>#include <fstream>#include <cstring>#include <algorithm>#define MAXN 20#define cin fin#define cout foutusing namespace std;ifstream fin("wormhole.in");ofstream fout("wormhole.out");int n, ans = 0;pair<int, int> wormholes[MAXN];int next[MAXN], pairs[MAXN];bool visit[MAXN];// 判断无限循环bool isCycle() { for (int i = 0; i < n; i++) { int v = i; int cnt = 0; while (true) { if (cnt >= 2*n) return true;// 感谢dyt同学找出的bug, // 起初认为判断cnt >= n即可, 但 2 1 2 1就是一个反例 v = pairs[v]; if (next[v] == 0) break; v = next[v]; cnt++; } } return false;}void dfs(int step) { if (step == n / 2) { if(isCycle()) { ans++; } } else { //先找一个未被标记的s int s = 0; for (int i = 0; i < n; i++) { if (!visit[i]) { s = i; visit[s] = true; break; } } //再枚举所有的未被标记的黑洞,与之配对,继续搜索 for (int i = 0; i < n; i++) { if (!visit[i]) { visit[i] = true; pairs[i] = s; pairs[s] = i; dfs(step+1); visit[i] = false;//回溯 } } visit[s] = false; //回溯 }}int main() { ios::sync_with_stdio(false); cin >> n; memset(next, 0, sizeof(next)); memset(wormholes, 0, sizeof(wormholes)); for (int i = 0; i < n; i++) { // 对pair<int, int>用sort排序,默认是先按照first,在按照second排序 // 所以 second 为 x, first 为 y cin >> wormholes[i].second >> wormholes[i].first; } // 先按y轴,再按x轴排序 (谢谢认真看我代码的ljj给我纠正。) // 这样同一行的黑洞(y相同,x不相同)排序后序号就是相邻的,方便寻找next[] sort(wormholes, wormholes+n); for (int i = 0; i < n-1; i++) { //next[i] 就是右边的第一个黑洞,或者出界,用0表示 if (wormholes[i+1].first == wormholes[i].first) { next[i] = i+1; } } dfs(0); cout << ans << endl; return 0;}
- USACO-Section1.3 Wormholes [搜索]
- USACO-Section1.3 Wormholes
- USACO-Section1.3 Wormholes
- USACO-Section1.3 Wormholes 【深度优先搜索】【暴力枚举】
- USACO-Section1.3Wormholes[其他]
- USACO-Section1.3 Prime Cryptarithm [搜索]
- 【USACO】Wormholes(暴力搜索)
- USACO-Section 1.3 Wormholes[搜索]
- usaco 1.1.3 wormholes
- USACO-Section1.4 Mother's Milk [搜索]
- USACO Section1.3 混合牛奶
- USACO section1.3 Mixing Milk
- usaco.section1.3 wormhole(枚举)
- USACO Section1.3 Mixing Milk
- USACO Section1.3 Barn Repair
- USACO Section1.3 Prime Cryptarithm
- USACO Section1.3 Combination Lock
- USACO-Section1.3 Mixing Milk
- 模板方法模式
- AVL树
- ubuntu16.04安装ibus中文输入法
- SoapUI5.2.1之REST参数
- Struts2,Spring,Hibernate三大框架的整合(SSH)
- USACO-Section1.3 Wormholes [搜索]
- JS 实现 python 中 Array.count
- 算法导论——13.1红黑树的性质
- Understanding LSTM Networks
- 最小树形图
- Golang学习笔记 数据类型和变量
- 权限概念
- vue开发:vue,angular,react数据双向绑定原理分析
- 在字符串中找出第一个只出现一次的字符