bin巨专题一 简单搜索(更新中

A--棋盘问题

POJ-1321

链接: https://vjudge.net/problem/15202/origin

类似n皇后问题,需要注意的是dfs的边界问题(t在此处

思路:当前走到i/u行j列,判断该点是否可以放棋子,不可以就j++,可以就dfs(i + 1),对放的棋子数进行计数,若等于k则return,记得状态还原。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 const int N = 20;
 7 
 8 int n, k, flag;
 9 char g[N][N];
10 bool row[N];
11 
12 void dfs(int u, int x){
13     if(x == k) {
14         flag ++;
15         return;
16     }
17     
18     for(int i = u; i < n ; i ++ ){
19         for(int j = 0; j < n; j ++ ){
20             if(g[i][j] != '.' && !row[j]){
21             row[j] = true;
22             dfs(i + 1, x + 1);
23             row[j] = false;
24             }
25         }
26     }
27     return;
28 }
29 
30 int main()
31 {
32     while(scanf("%d %d", &n, &k) != EOF){
33         if(n ==-1 && k == -1) break;
34         flag = 0;
35         for(int y = 0; y < n; y ++ )
36             for(int z = 0; z < n; z ++ )
37                 cin>>g[y][z];
38         dfs(0, 0);
39         printf("%d\n",flag);
40     }
41     return 0;
42 }
View Code

B--Dungeon Master

POJ-2251

链接: https://vjudge.net/problem/15203/origin

一个三维地图上的bfs,注意三维数组的存储

扫描二维码关注公众号,回复: 7326126 查看本文章

变量设了太多,没有注意到重复了,改了很久才发现……

以后用结构体了orz

提交的时候选用G++,然后就是不要再用auto了

思路: 从起点开始向六个方向进行搜索,其他和二维地图相同。

代码:

 1 #include <iostream>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 typedef pair<int, int> PII;
 9 queue<PII> q;//y z 
10 queue<int> u;//x
11 const int N = 35;
12 int d[N][N][N];
13 char g[N][N][N];
14 int l, r, c;//l:z  r:y  c:x
15 int sx, sy, sz;//终点 
16 int tx, ty, tz;//起点 
17 char str[2];
18 int bfs()
19 {
20     memset(d, -1, sizeof(d));
21     d[tz][ty][tx] = 0;
22     q.push({ty, tz});
23     u.push(tx);
24     int dx[6] = {0, 0, -1, 1, 0, 0};
25     int dy[6] = {-1, 1, 0, 0, 0, 0};
26     int dz[6] = {0, 0, 0, 0, 1, -1};//前后左右上下
27     
28     while(q.size()){
29         pair<int, int> t; 
30         t = q.front();
31         int a = t.first;//y
32         int b = u.front();//x
33         int o = t.second;//z
34         q.pop();
35         u.pop();
36         for(int i = 0; i < 6; i ++ ){
37             int x = b + dx[i];
38             int y = a + dy[i];
39             int z = o + dz[i];
40             if(x >= 0 && x < c && y >= 0 && y < r && z >= 0 && z < l && d[z][y][x] == -1 && (g[z][y][x] == '.' || g[z][y][x] == 'E'))
41             {
42                 d[z][y][x] = d[o][a][b] + 1;
43                 q.push({y, z});
44                 u.push(x);    
45             }
46             if(x == sx && sy == y && sz == z) break;
47         }
48     }
49     return d[sz][sy][sx];
50 }
51 
52 int main()
53 {
54     while(cin>>l>>r>>c){
55         gets(str);
56         if(l == 0 && r == 0 && c == 0) break;
57         for(int i = 0; i < l; i ++ ){
58             for(int j = 0; j < r; j ++ ){
59                 scanf("%s", g[i][j]);
60             }
61         }
62         
63         for(int i = 0; i < l; i ++ ){
64             for(int j = 0; j < r; j ++ ){
65                 for(int k = 0; k < c; k ++ ){
66                     if(g[i][j][k] == 'E') sx = k, sy = j, sz = i;
67                     if(g[i][j][k] == 'S') tx = k, ty = j, tz = i;
68                 }
69             }
70         }
71         int p = bfs();
72         if(p == -1) printf("Trapped!\n");
73         else printf("Escaped in %d minute(s).\n", p);
74     }
75     return 0;
76 }
View Code

C--Catch That Cow

POJ-3278

链接: https://vjudge.net/problem/15204/origin

在一维地图上进行bfs寻找最短路径

有三种操作:加1,减1,乘2

需要进行剪枝,否则会mle

当n>=k时,直接输出n-k即可

注意标记状态(忘记标记一直mle

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <cmath>
 6 
 7 using namespace std;
 8 const int N = 1e5 + 10;
 9 bool flag[N];
10 int d[N];
11 int n, k;
12 queue<int> q;
13 int bfs(int a, int b){
14     memset(d, -1, sizeof d);
15     d[a] = 0;
16     q.push(a);
17     while(q.size()){
18         int p = q.front();
19         q.pop();
20         if(p-1 >= 0 && !flag[p-1]) {
21             q.push(p-1);
22             d[p-1] = d[p] + 1;
23             flag[p-1] = true;
24         }
25         if(p+1 <= N && !flag[p+1]){
26             q.push(p+1);
27             d[p+1] = d[p] + 1;
28             flag[p+1] = true;
29         }
30         if(p*2 <=N && !flag[p*2]){
31             q.push(p*2);
32             d[p*2] = d[p] + 1;
33             flag[p*2] = true;
34         }
35         if(p-1 == b || p+1 == b || p*2 == b) break;
36     }
37     return d[b];
38 }
39 
40 int main()
41 {
42     cin>>n>>k;
43     int ans;
44     while(q.size()) q.pop();
45     if(n >= k) ans = n - k;
46     else ans = bfs(n, k);
47     cout<<ans<<endl;
48     return 0;
49 }
View Code

D-Fliptile

POJ-3279

链接:https://vjudge.net/problem/17522/origin

这题我写了好多天……

需要用二进制对第一排状态进行枚举

于是学习了位运算的相关操作以及状态压缩

参考博客:https://blog.csdn.net/loy_184548/article/details/50949972

可以说是写的非常清楚了

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <algorithm>
 6 #include <cmath>
 7 
 8 using namespace std;
 9 
10 const int maxn = 16;
11 int m, n;
12 const int dx[5] = {-1, 0, 0, 0, 1};
13 const int dy[5] = {0, -1, 0, 1, 0};
14 int tile[maxn][maxn];
15 int opt[maxn][maxn];//最优解
16 int flip[maxn][maxn];//保存中间结果
17 
18 int get(int x, int y){
19     int c = tile[x][y];
20     for(int d = 0; d < 5; d ++ ){
21         int x2 = x + dx[d], y2 = y + dy[d];
22         if(0 <= x2 && x2 < m && 0 <= y2 && y2 < n)
23             c += flip[x2][y2];
24     }
25     return c % 2;
26 }
27 
28 int calc(){
29     for(int i = 1; i < m; i ++ ){
30         for(int j = 0; j < n; j ++ ){
31             if(get(i - 1, j)) flip[i][j] = 1 ;
32         }
33     }
34     for(int i = 0; i < n; i ++ ){
35         if(get(m - 1, i) != 0) return -1;
36     }
37     int res = 0;
38     for(int i = 0; i < m; i ++ ){
39         for(int j = 0; j < n; j ++ )
40             res += flip[i][j];
41     }
42     return res;
43 }
44 
45 void solve()
46 {
47     int res = -1;
48     for(int i = 0; i < 1 << n; i ++ ){
49         memset(flip, 0, sizeof flip);
50         for(int j = 0; j < n; j ++ ){
51             flip[0][n - j - 1] = i >> j & 1;
52         }
53         int num = calc();
54         if(num >= 0 && (res < 0 || num < res)){
55             res = num;
56             memcpy(opt, flip, sizeof flip);
57         }
58     }
59     if(res < 0) printf("IMPOSSIBLE\n");
60     else {
61         for(int i = 0; i < m; i ++ ){
62             for(int j = 0; j < n; j ++ ){
63                 printf("%d ", opt[i][j]);
64             }
65             printf("\n");
66         }
67     }
68 }
69 
70 int main()
71 {
72     cin>>m>>n;
73     for(int i = 0; i < m; i ++ )
74         for(int j = 0; j < n; j ++ )
75             cin>>tile[i][j];
76     solve();
77     return 0;
78 }
View Code

 位运算的一些操作

1.空集  0
2.只含第i个元素的集合  1 << i
3.含有全部n个元素的集合  (1 << n) - 1
4.判断第i个元素是否属于s  if(s >> i & 1)
5.向集合中加入第i个元素 s | 1 << i
6.取出第i个元素  s >> i & 1
7.从集合中去掉第i个元素  s & ~(1 << i)
8. s + t  s|t
9.st  s & t

用二进制枚举状态
1.枚举所有子集   
    for(int s = 0; s < 1 << n; s ++ )
2.枚举某个集合sup的子集
    int sub = sup;
    do{sub = (sub - 1) & sup;} while(sub != sup);
3.枚举集合的大小为k的子集
    字典序最小子集为 comb = (1 << k) - 1
    每次循环求出最低位 x = comb & - comb
    y = comb + x;
    comb = ((comb & ~y) / x >> 1 ) | y;

E-Find the Multiple

POJ-1426

链接:https://vjudge.net/problem/15205/origin

题意:给出一个数,找到它的一个倍数且该倍数(10进制下)只由0和1组成

坑点:题目里说这个倍数不超过300位,我以为要用字符串,准备换java写了, 结果发现long long就能过

   还有就是用c++提交t了,g++过了

待解决的疑惑:查了一些题解, 发现很多人用dfs过的, 搜到第19层就不搜了,不太明白为什么(

思路:简单的bfs,从1开始搜,搜过一个数之后,将它的十倍和十倍加一这两个数压进队列继续搜

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <queue>
 7 
 8 using namespace std;
 9 
10 long long bfs(int x){
11     queue<long long> q;
12     q.push(1);
13     while(q.size()){
14         long long f = q.front();
15         q.pop();
16         if(f % x == 0)
17             return f;
18         q.push(f * 10);
19         q.push(f * 10 + 1);
20     }
21     return -1;
22 }
23 
24 int main()
25 {
26     int n;
27     while(scanf("%d", &n) != EOF && n != 0){
28         long long x = bfs(n);
29         printf("%lld\n", x);
30     }
31     return 0;
32 }
View Code

猜你喜欢

转载自www.cnblogs.com/moomight/p/11317770.html