SCUT ACM PLACTICE # 3 二进制枚举,深搜,广搜
2017-01-24 13:30
253 查看
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 ); } 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+10 int 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 ; 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 ; 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; }
相关文章推荐
- POJ 1873 The Fortified Forest 凸包 二进制枚举
- UVA.10325 The Lottery (组合数学 容斥原理 二进制枚举)
- acm-简单枚举-除法(水题)
- Java sdut acm 1959 简单枚举类型——植物与颜色
- Atcoder 045 -二进制枚举
- ACM二进制运算技巧
- Water Gate Management(二进制枚举组合排列模板 n个数的子集)
- ACM学习小记____枚举
- uva-1151-Buy or Build-二进制枚举子集,并查集,最小生成树,kruskal
- ACM--枚举暴力--HDOJ 1017--A Mathematical Curiosity--水
- 操纵不同二进制位代表不同意义的枚举代码示例
- uva11464(二进制枚举)
- poj 1416 Shredding Company 二进制枚举
- ACMjava简单枚举除法,分数拆分,双基回文数,最大乘积
- ZOJ 3665 Yukari's Birthday 第37届ACM/ICPC长春赛区现场赛K题 (水题,枚举,二分)
- 二进制枚举及容斥
- 二进制枚举的实现
- POJ 2429 GCD & LCM Inverse(大整数素因子分解+二进制枚举)
- Water Gate Management(二进制枚举组合排列模板 n个数的子集)
- HDU 4810 Wall Painting【二进制+异或+暴力枚举】