搜索题【入门】
2015-12-04 15:24
232 查看
搜索题【入门】
HZNU-1507-K进制数题目链接:HZNU-1507
题目大意:给出K进制数的位数,问存在多少种情况,不含两个连续的0,且不以0开头
题目思路:DFS
[code]#include <vector> #include <map> #include <set> #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <string> #include <cstring> using namespace std; int ans = 0; int n,k; void dfs(int x,int y) { if (y == 0) { ans++; return; } if (x != 0) dfs(0,y-1); for (int i = 1; i < k; i++) { dfs(i,y-1); } } int main(){ cin >> n >> k; for (int i = 1; i < k; i++) dfs(i,n-1); cout << ans << endl; return 0; }
HDU-2553-N皇后问题
题目链接:HDU-2553
题目大意:在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。你的任务是,对于给定的N,求出有多少种合法的放置方法。
题目思路:采用回溯。一行一行的放皇后, 然后再递归判断是否与之前已放好的皇后有冲突,一旦有冲突,则不需要继续下一行的搜索,直接返回(省去不必要的枚举)。
以下是代码:
[code]#include <vector> #include <map> #include <set> #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <string> #include <cstring> using namespace std; int line[15]; int n; int tot = 0; int ans[15]; void dfs(int row)//第row行 { if (row == n) // { tot++; return; } for (int i = 0; i < n; i++) { line[row] = i; //假设第row行皇后放在i这列 int ok = 1; for (int j = 0; j < row; j++) { //判断前面row-1行,i列是否放了皇后,以及对角线是否有冲突 if (line[j] == i || line[row] - row == line[j] - j || line[row] + row == line[j] + j) { ok = 0; break; } } if (ok) { dfs(row + 1); } } } int main(){ for (n = 1; n <= 10; n++) //预处理,防止超时 { tot = 0; dfs(0); ans = tot; } while(cin >> n && n) { cout << ans << endl; } return 0; }
HDU-1016–Prime Ring Problem(素数环)
题目链接:HDU-1016
题目大意:输入正整数n,把整数1,2,3,…,n组成一个环,使得相邻两个整数之和为素数。输出时从整数1开始。
题目思路:DFS,注意判断最后一个和第一个数相加也是素数
以下是代码:
[code]#include <vector> #include <map> #include <set> #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <string> #include <cstring> using namespace std; int prm[100000]; const int MAXV = 1e5; bool isPrime[MAXV+1]; int size=0; int A[30]; int vis[30]; //获得素数 void getPrime() { memset(isPrime, true, sizeof(isPrime)); int sq = sqrt((double)MAXV) + 1; int i,j,k; for(i = 2;i <= sq; i++) if(isPrime[i]) for(j = 2,k = MAXV/i+1;j < k;j++) isPrime[i*j] = false; for( i = 2 ; i <= MAXV; i++) if(isPrime[i]) prm[size++] = i; isPrime[0] = isPrime[1] = false; } int n; int cnt = 1; int first = 1; void dfs(int cur) { if (cur == n + 1 && isPrime[A + A[1]]) { printf("%d",A[1]); for(int i = 2; i <= n; i++) { printf(" %d",A[i]); } printf("\n"); return; } for (int i = 1; i <= n; i++) { if (!vis[i] && isPrime[i + A[cur - 1]]) { vis[i] = 1; A[cur] = i; dfs(cur + 1); vis[i] = 0; } } } int main(){ getPrime(); while(scanf("%d",&n) != EOF) { printf("Case %d:\n",cnt++); memset(vis,0,sizeof(vis)); memset(A,0,sizeof(A)); vis[1] = 1; A[1] = 1; if (n % 2 != 1) dfs(2); printf("\n"); } return 0; }
HDU-1241-Oil Deposits
题目链接:HDU-1241
题目思路:在一个矩阵里,有些格子是‘@’,有些不是,相邻(上、下、左、右、左上、右上、左下、右下)的格子如果也是‘@’,那么他们属于同一个矿井,问总共有多少个矿井。
题目思路:DFS,求连通块个数。
以下是代码:
[code]#include <vector> #include <map> #include <set> #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <string> #include <cstring> using namespace std; string s[101]; int vis[105][105]; int flag = 0; int m,n; void dfs(int c,int r) { if (c >= m || c < 0 || r >= n || r < 0) return; if (vis[c][r] || s[c][r] != '@') return; vis[c][r] = 1; if (s[c][r] == '@') flag = 1; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; dfs(c + i,r + j); } } } int main(){ while(cin >> m >> n) { if (m == 0 && n == 0) break; for (int i = 0; i < m; i++) { cin >> s[i]; } int ans = 0; memset(vis,0,sizeof(vis)); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (s[i][j] == '@') { dfs(i,j); if (flag) ans++; flag = 0; } } } cout << ans << endl; } return 0; }
HDU-1312-Red and Black
题目链接:HDU-1312
题目大意:‘@’代表人其实位置,‘.’代表可走格子,‘#’代表‘墙’。问这个人最多能走几个格子。可以走的方向有(上、下、左、右)四个方向。
题目思路:DFS,从‘@’开始搜,如果是可走位置继续搜,如果碰到墙则停止该条路的搜索。
以下是代码:
[code]#include <vector> #include <map> #include <set> #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <string> #include <cstring> using namespace std; string s[25]; int vis[25][25]; int w,h; int ans = 0; void dfs(int c,int r) { if (c >= h || c < 0 || r >= w || r < 0) return; if (vis[c][r] || s[c][r] == '#') return; vis[c][r] = 1; ans++; dfs(c + 1,r); dfs(c - 1,r); dfs(c,r + 1); dfs(c,r - 1); } int main(){ while(cin >> w >> h) { if (w == 0 && h == 0) break; int poi = -1,poj = -1; ans = 0; memset(vis,0,sizeof(vis)); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { cin >> s[i][j]; if (s[i][j] == '@') poi = i,poj = j; } } dfs(poi,poj); cout << ans << endl; } return 0; }
HDU-1584-蜘蛛牌
题目链接:HDU-1584
题目大意:小的牌移动到大的牌上面。给出每个牌的位置,问叠成一堆牌的最小移动距离
题目思路:DFS+剪枝
以下是代码:
[code]#include <vector> #include <map> #include <set> #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <string> #include <cstring> using namespace std; int p[20]; int vis[20]; int ans = 9999999; void dfs(int cur,int sum) //cur表示解决了几张牌,sum表示目前移动的距离 { if (sum >= ans) return; //剪枝 if (cur == 9) //10是保持不动 { ans = sum; return; //回溯 } for (int i = 1; i < 10; i++) { if (!vis[i]) //这张牌没有被处理过 { vis[i] = 1; for (int j = i + 1; j <= 10; j++) { if (!vis[j]) { dfs(cur + 1,sum + abs(p[i] - p[j])); //小的牌叠到大的牌上面 break; //注意不要再这个地方回溯 如果回溯了 就像是又一个全排列 而且牌得移动不合理,比如2移到6了,结果回溯就直接跳过3~6到了7的下面 } } vis[i] = 0; //这里回溯 } } } int main(){ int t; scanf("%d",&t); while(t--) { memset(vis,0,sizeof(vis)); ans = 9999999; for (int i = 1; i <= 10; i++) { int num; scanf("%d",&num); p[num] = i; //牌面为num在第i个位置 } dfs(0,0); printf("%d\n",ans); } return 0; }
相关文章推荐
- iOS将控制台Log日志转为输出为文本文件
- Oracle创建删除用户、角色、表空间、导入导出、...命令总结
- UIWindow & UIWindowLevel笔记
- Android学习-----Button点击事件几种写法
- hdu 4902 Nice boat 线段树
- 三大重磅福利!曲面电视现史上最佳买点
- IOS Iphone震动 和 提示音
- 验证docker的Redis镜像也存在未授权访问漏洞
- iOS--深浅拷贝深析
- Linux查找、安装&卸载命令学习
- LINUX下开启apache时出现Address already in use: make_sock: could not bind to address [::]:80
- Exception in thread "main" java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Wi
- youzhu例子新知识
- 总结使用Unity 3D优化游戏运行性能的经验
- AngularJs页面传参的几种方式
- mysqli连接数据库函数
- C++11 右值引用
- linux mmc驱动子系统
- (六十二)第四章总结——《C++ Primer Plus 第6版 中文版》
- Android之WindowManager