SCUT ACM PLACTICE # 3 二进制枚举,深搜,广搜
来源:互联网 发布:淘宝名鞋库 编辑:程序博客网 时间:2024/05/16 01:21
Links:https://vjudge.net/contest/145674#overview
A - 搜索 初心者向 HDU - 2553
简单搜索n皇后,主要是要处理判断是否能放置的问题。
这次我用了四个数组来判断行,列,主对角和副对角是否已经有棋子。
#include<iostream>#include<string.h>#include<string>#include<math.h>#include<stdio.h>using namespace std;int n;bool h[50], l[50], z[50], f[50];int ans[15];int dfs(int x, int y){ if (y == n){ return 1; } int ans = 0; h[x] = 1, l[y] = 1, z[x + y] = 1, f[x - y + 20] = 1; for (int i = 1; i <= n; i++){ if (h[i] == 0 && l[y + 1] == 0 && z[i + y + 1] == 0 && f[i - y - 1 + 20] == 0){ ans += dfs(i, y + 1); } } h[x] = 0, l[y] = 0, z[x + y] = 0, f[x - y + 20] = 0; return ans;}int main(){ for (int i = 1; i <= 10; i++){ for (int j = 1; j <= i; j++){ n = i; ans[i] += dfs(j, 1); } } while (~scanf("%d", &n),n!=0){ printf("%d\n", ans[n]); } return 0;}
B - 搜索 中级者向 POJ - 3278
广搜,能够对当前数字+1,-1,*2,求最小步骤从初始数字到终末数字。
#include<iostream>#include<string.h>#include<string>#include<stdio.h>#include<queue>using namespace std;int fx, fy;int astep;int v[300005];struct point{ int x; int s;}beg;queue<point> que;int bfs(){ int ans = -1; int k = fy > fx ? (fy - fx) : (fx - fy); while (!que.empty()){ point cnt = que.front(); que.pop(); if (astep != -1 && cnt.s > astep||cnt.x<0||cnt.x>105000||cnt.s>k){ continue; } if (cnt.x == fy){ if (astep == -1){ astep = cnt.s; } else{ astep = astep < cnt.s ? astep : cnt.s; } continue; } if (v[cnt.x + 1] == 0){ que.push({ cnt.x + 1, cnt.s + 1 }); v[cnt.x + 1] = 1; } if (cnt.x-1>=0&&v[cnt.x - 1] ==0){ que.push({ cnt.x - 1, cnt.s + 1 }); v[cnt.x -1] = 1; } if (cnt.x != 0 && v[cnt.x * 2] == 0){ que.push({ cnt.x * 2, cnt.s + 1 }); v[cnt.x*2] = 1; } } return ans;}int main(){ scanf("%d%d", &fx, &fy); astep = -1; beg.x = fx, beg.s = 0; que.push(beg); bfs(); printf("%d",astep ); return 0;}
C - 搜索 中级者向 POJ - 2488
八方向跳棋,求最终整个棋盘都跳满的路径,要求输出路径比较麻烦,dfs过程中在相应的格子记录上这是跳的第几步就行了。
#include<iostream>#include<string.h>#include<string>#include<algorithm>#include<stdio.h>using namespace std;int fx, fy,total;bool r;int v[24][24];int dx[8] = {-1,1,-2,2,-2,2,-1,1};int dy[8] = {-2,-2,-1,-1,1,1,2,2};void dfs(int x,int y,int n){ if (r == false) v[x][y] = n; if (n == total){ r = true; return; } for (int i = 0; i < 8; i++){ int nx = x + dx[i], ny = y + dy[i]; if (nx>0 && nx <= fx&&ny > 0 && ny <= fy&&v[nx][ny] == 0&&r==false){ dfs(nx, ny, n + 1); if (r == true){ break; } } } if (r==false) v[x][y] = 0;}void pf(int x, int y,int n){ putchar(y + 64); printf("%d", x); if (n == total){ return; } for (int i = 0; i < 8; i++){ if (v[x + dx[i]][y + dy[i]] == n + 1){ pf(x + dx[i], y + dy[i], n + 1); } }}int main(){ int t; scanf("%d", &t); for(int k=1;k<=t;k++){ int ax, ay; r = false; memset(v, 0, sizeof(v)); scanf("%d%d", &fx, &fy); total = fx*fy; for (int i = 1; i <= fx; i++){ for (int j = 1; j <= fy; j++){ dfs(i, j,1); if (r == true){ ax = i, ay = j; break; } } if (r == true)break; } printf("Scenario #%d:\n", k); if (r == false){ printf("impossible\n\n"); } else{ pf(ax, ay,1); printf("\n\n"); } } return 0;}
D - 搜索 初心者向
三维地图bfs最短路径,方向变成6个。
#include<iostream>#include<string.h>#include<string>#include<stdio.h>#include<queue>using namespace std;int l, r, c,ans;int map[32][32][32];bool v[32][32][32];int dl[6] = { 0, 0, 0, 0, 1, -1 };int dx[6] = { -1, 0, 0, 1, 0, 0 };int dy[6] = { 0, -1, 1, 0, 0, 0 };struct point{ int l; int x; int y; int s;}beg;queue<point> que;int bfs(){ int ans = -1; while (!que.empty()){ point cnt = que.front(); que.pop(); if (map[cnt.l][cnt.x][cnt.y]=='E'){ ans = cnt.s; break; } for (int i = 0; i < 6; i++){ point np={ cnt.l + dl[i], cnt.x + dx[i], cnt.y + dy[i], cnt.s + 1 }; if (np.l >= 0 && np.l<l&&np.x>=0 && np.x<r&&np.y>=0 && np.y < c){ if (map[np.l][np.x][np.y] != '#'&&v[np.l][np.x][np.y]==0){ que.push(np); v[np.l][np.x][np.y] = 1; } } } } while (!que.empty()){ que.pop(); } return ans;}int main(){ while (scanf("%d%d%d", &l, &r, &c)){ memset(v, 0, sizeof(v)); getchar(); if (l == 0){ return 0; } for (int i = 0; i < l; i++){ for (int j = 0; j < r; j++){ for (int k = 0; k < c; k++){ map[i][j][k]=getchar(); if (map[i][j][k] == 'S'){ beg.l = i, beg.x = j, beg.y = k,beg.s=0; v[i][j][k] = 1; } } getchar(); } getchar(); } que.push(beg); int ans = bfs(); if (ans == -1){ printf("Trapped!\n"); } else{ printf("Escaped in %d minute(s).\n",ans); } } return 0;}
E - 搜索(DFS) 初心者向
连通块计数,经典的dfs
#include<iostream>#include<string.h>#include<string>#include<math.h>#include<stdio.h>using namespace std;int n, m;char map[105][105];int dx[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };int dy[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };void dfs(int x, int y){ map[x][y] = '.'; for (int i = 0; i < 8; i++){ int nx = x + dx[i], ny = y + dy[i]; if (nx >= 0 && nx < n&&ny >= 0 && ny < m&&map[nx][ny] == 'W'){ dfs(nx, ny); } }}int main(){ scanf("%d%d", &n, &m); for (int i = 0; i < n; i++){ getchar(); for (int j = 0; j < m; j++){ map[i][j] = getchar(); } } int ans = 0; for (int i = 0; i < n; i++){ for (int j = 0; j < m; j++){ if (map[i][j] == 'W'){ dfs(i, j); ans++; } } } printf("%d", ans); return 0;}
F - 搜索(BFS)+模拟 中级者向 POJ - 3083
给出地图求三种走法的路径:左扶墙,右扶墙,最短路。
#include<iostream>#include<string.h>#include<string>#include<stdio.h>#include<queue>using namespace std;int fx, fy;char map[45][45];bool v[45][45];int dx1[4] = { 0, -1, 0, 1, };int dy1[4] = { 1, 0, -1, 0, };int dx2[4] = { 0, -1, 0, 1, };int dy2[4] = { -1, 0, 1, 0, };struct point{ int x; int y; int s;}beg;queue<point> que;int bfs(){ int ans = -1; while (!que.empty()){ point cnt = que.front(); que.pop(); if (map[cnt.x][cnt.y] == 'E'){ ans = cnt.s; break; } for (int i = 0; i < 4; i++){ point np = { cnt.x + dx1[i], cnt.y + dy1[i], cnt.s + 1 }; if (np.x >= 0 && np.x<fx&&np.y >= 0 && np.y < fy){ if (map[np.x][np.y] != '#'&&v[np.x][np.y] == 0){ que.push(np); v[np.x][np.y] = 1; } } } } while (!que.empty()){ que.pop(); } return ans;}int dfs(point cnt,int dir){ if (map[cnt.x][cnt.y] == 'E'){ return cnt.s; } for (int i = dir-1;; i++){ int ci = i < 0 ? i + 4:i; point newp = { cnt.x + dx1[ci % 4], cnt.y + dy1[ci % 4], cnt.s + 1 }; if (newp.x >= 0 && newp.x < fx&&newp.y >= 0 && newp.y < fy&&map[newp.x][newp.y] != '#'){ dfs(newp, i); break; } }}int idfs(point cnt, int dir){ if (map[cnt.x][cnt.y] == 'E'){ return cnt.s; } for (int i = dir-1;; i++){ int ci = i < 0 ? i + 4 : i; point newp = { cnt.x + dx2[ci % 4], cnt.y + dy2[ci % 4], cnt.s + 1 }; if (newp.x >= 0 && newp.x < fx&&newp.y >= 0 && newp.y < fy&&map[newp.x][newp.y] != '#'){ idfs(newp, i); break; } }}int main(){ int t; scanf("%d", &t); while (t--){ scanf("%d%d", &fy, &fx); memset(v, 0, sizeof(v)); getchar(); for (int i = 0; i < fx; i++){ for (int j = 0; j < fy; j++){ map[i][j] = getchar(); if (map[i][j] == 'S'){ beg.x = i, beg.y = j, beg.s = 1; v[i][j] = 1; } } getchar(); } que.push(beg); int ans = bfs(); int ans1 = dfs(beg,0); int ans2 = idfs(beg, 0); printf("%d %d %d\n", ans2, ans1, ans); } return 0;}
G - 欧拉图 初心者向 HDU - 1878
判断欧拉回路的题。并查集判连通。
#include<iostream>#include<string.h>#include<string>#include<stdio.h>using namespace std;int n, m;int point[1005];int f[1005];int F(int x){ if (f[x] == x)return x; else{ return f[x] = F(f[x]); }}int main(){ int x, y; while (~scanf("%d", &n)){ if (n == 0){ return 0; } scanf("%d", &m); for (int i = 1; i <= n; i++){ f[i] = i; } memset(point, 0, sizeof(point)); for (int j = 0; j < m; j++){ scanf("%d%d", &x, &y); point[x]++; point[y]++; f[F(x)] = F(y); } int ji = 0; int ff = F(1); for (int i = 1; i <= n; i++){ if ((point[i] % 2) != 0||F(i)!=ff){ ji = 1; break; } } if (ji == 0){ printf("%d\n",1); } else{ printf("%d\n",0); } } return 0;}
H - 欧拉图 中级者向 POJ - 2230
就是输出一条欧拉回路。
#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stdio.h>using namespace std;#define maxn 50000+10int n, m;struct Edge{ int to; bool vis;};vector<Edge>G[maxn];void euler(int u){ int num = G[u].size(); for (int i = 0; i < num; i++){ if (G[u][i].vis == 0){ G[u][i].vis = 1; euler(G[u][i].to); } } printf("%d\n", u);}int main(){ scanf("%d%d", &n, &m); int x, y; for (int i = 0; i < m; i++){ scanf("%d%d", &x, &y); Edge a = { y, 0 }; Edge b = { x, 0 }; G[x].push_back(a); G[y].push_back(b); } euler(1); return 0;}
I - 欧拉图 上级者向 POJ - 1780
要求把所有可能的密码已最短长度也就是最大的重叠度输出出来,对于n位的密码,答案每往后输出一位,就会与前n-1位构成一个新密码,转换成以n-1位数字为点的欧拉回路,因为除了最后n-1位,一但有一个n-1位数字后面新增0-9都已经在前面输出过了,那么就无法只新增一位来构造一个新密码。
要求非递归,看了别人的代码看了好久才看懂。
#include<cstdio>#include<cstring>#include<queue>using namespace std;int n, ppow[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };int cnt[1000000], stack[1000010];bool vis[1000000];void dfs(){ memset(vis, 0, sizeof(vis));// vis[0] = 1; memset(cnt, 0, sizeof(cnt)); int top = -1; stack[++top] = 0; int total = ppow[n]; while (top!=total){ int v = stack[top]; if (cnt[v] ==10 ){ vis[v] = 0; cnt[v] = 0; top--; continue; } int newn = (v * 10 + cnt[v]) % ppow[n]; cnt[v]++; if (vis[newn]){ continue; } vis[newn] = 1; stack[++top] = newn; } for (int i = 1; i <= top; ++i) putchar(stack[i] % 10 + '0');}int main(){ while (~scanf("%d", &n) && n){ for (int i = 1; i<n; ++i) putchar('0'); dfs(); putchar('\n'); } return 0;}
J - 二叉树 中级者向
给出二叉树的前序中序遍历,要求给出后序遍历的结果。分治递归就行。
#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stdio.h>using namespace std;int n;int pre[1005];int in[1005];int cou,acount;void findans(int beg, int end){ if (beg == end){ return; } int cnt = pre[cou++]; int mid; for (int i = beg; i < end; i++){ if (in[i] == cnt){ mid = i; break; } } findans(beg, mid); findans(mid + 1, end); printf("%d", in[mid]); if (acount <n-1){ printf(" "); } acount++;}int main(){ while (~scanf("%d", &n)){ cou = 0,acount=0; for (int i = 0; i < n; i++){ scanf("%d", &pre[i]); } for (int i = 0; i < n; i++){ scanf("%d", &in[i]); } findans(0, n ); printf("\n"); }}
K - 二进制枚举 初心者向
输出比给定数字大的只包含4和7且4和7的数量相等的最小数字,枚举每一位是4或7就行。
#include<iostream>#include<string.h>#include<string>#include<stdio.h>using namespace std;long long num;long long ans;void dfs(long long n,int fn,int sn){ if (ans!=0&&n >ans||n>num*100 ){ return; } if (fn == sn&&n>=num){ if (ans == 0){ ans = n; } else{ ans = ans < n ? ans : n; } } dfs(n * 10 + 4,fn+1,sn); dfs(n * 10 + 7,fn,sn+1);}int main(){ while (cin >> num){ ans = 0; dfs(0, 0, 0); cout << ans << endl; } return 0;}
L - 二进制枚举 初心者向 HDU - 1557
简单的枚举题。
#include<iostream>#include<string.h>#include<stdio.h>using namespace std;int n;int p;int v[25];int dfs(int x, int y,int num){ if (y == n-1){ if (num > p && (num - v[x] <= p)){ return 1; } else {return 0;} } int ans = 0; if (y+1 == x){ ans += dfs(x, y + 1, num + v[y+1]); } else{ ans += dfs(x, y + 1, num); ans += dfs(x, y + 1, num + v[y+1]); } return ans;}int main(){ int t; cin >> t; while (t--){ int total = 0; cin >> n; for (int i = 0; i < n; i++){ cin >> v[i]; total += v[i]; } p = total / 2; for (int i = 0; i < n; i++){ cout << dfs(i, -1, 0); if (i < n - 1){ cout << " "; } } cout << endl; } return 0;}
M - 二进制枚举 初心者向 CodeForces - 202A
求字典序最大的回文字串。
#include<iostream>#include<string.h>#include<string>#include<stdio.h>using namespace std;string raw, ans;int length;bool pal(string a){ int len = a.length(); bool ans = true; for (int i = 0; i < len / 2; i++){ if (a[i] != a[len - i - 1]){ ans = false; break; } } return ans;}void dfs(int x,string cnt){ if (pal(cnt)){ if (ans == " "||cnt>ans){ ans = cnt; } } if (x == length - 1){ return; } dfs(x + 1, cnt + raw[x + 1]); dfs(x + 1, cnt);}int main(){ cin >> raw; ans = " "; length = raw.length(); dfs(-1, ""); cout << ans; return 0;}
0 0
- SCUT ACM PLACTICE # 3 二进制枚举,深搜,广搜
- SCUT ACM PLACTICE #2 贪心算法与哈夫曼树
- ACM之广搜
- 二进制压缩存储+广搜;
- poj 2923 Relocation 二进制状态压缩 深搜+广搜
- 小学生玩ACM----广搜
- ACM 深搜&广搜 Counting Sheep&Space Exploration
- ACM 广搜优先 Knight Moves
- ACM 广搜 Hero In Maze
- ACM 广搜 贪吃蛇&&Maze
- Scut
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- Manipulator explore
- 【剑指offer】面试题39-二叉树的深度
- 【OpenJudge】寻找山顶
- 每天10个前端知识点:各种宽高距离篇
- python3.6 mysql-connector-python 2.2.2
- SCUT ACM PLACTICE # 3 二进制枚举,深搜,广搜
- 理解本真的REST架构风格
- f7-Vue 控件2 表头标题 Badge数字 Block Block inner Block inset
- SpringBatch 数据库 Schema
- android 常用调用系统功能
- POJ 3278-Catch That Cow(BFS-一维广搜)
- CSS格式化排版
- ExecutorService与Executors例子的简单剖析
- 动态映射之结构体方式操作寄存器