搜索基础题

1.http://acm.hdu.edu.cn/showproblem.php?pid=1312

题意:在一个仅有红黑格子组成的矩形中,一个人只能走上下左右相邻黑色格子,问从起点开始共能走多少个格子?

’#‘:红色格子

’.': 黑色格子;

’@‘:起点 

BFS 和 DFS 都可以遍历所有走的点,每次走过一点时,计数++即可;

2.http://acm.hdu.edu.cn/showproblem.php?pid=1728

由题可知,在限制转弯数量的前提下 能够从一点走到另一个点即可;BFS 和 DFS都能求出解。我 DFS 还没实现

需要注意:1.点坐标是从 1 开始的。

     2.最短的路径可能不满足转弯数的限制。

     3.起点与终点重合。

超内存代码:已找到原因,完全是大意所致。贴在此处,希望自己以后再看时能一眼找到。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define N 105
 6 
 7 struct Pos
 8 {
 9     int x, y;
10     int turn;
11     int dire;
12 }S, E;
13 char map[N][N];
14 bool used[N][N][12][4];
15 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
16 int n, m, k;
17 
18 bool Judge (Pos s)
19 {
20     if (s.x>=1 && s.x<=m && s.y>=1 && s.y<=n && map[s.x][s.y]=='.' && !used[s.x][s.y][S.turn][S.dire] && s.turn <= k)
21         return true;
22     return false;
23 }
24 
25 bool  bfs ()
26 {
27     Pos Pre, Cur;
28     queue <Pos> Q;
29     while (!Q.empty ()) Q.pop();
30     memset (used, 0, sizeof used);
31 
32     S.dire = -1;
33     S.turn = 0;
34     used[S.x][S.y][S.turn][S.dire] = true;
35     Q.push (S);
36     while (!Q.empty ())
37     {
38         Pre = Q.front ();
39         Cur = Pre;
40         Q.pop();
41         if (Cur.x==E.x && Cur.y==E.y)
42             return true;
43         for(int i=0; i<4; i++)
44         {
45             Cur.x = Pre.x + dir[i][0];
46             Cur.y = Pre.y + dir[i][1];
47             Cur.turn = Pre.turn;
48             Cur.dire = i;
49             if (Cur.dire != Pre.dire && Pre.dire !=-1)
50                 Cur.turn++;
51             if (Judge (Cur))
52             {
53                 used[Cur.x][Cur.y][Cur.turn][Cur.dire] = true;
54                 Q.push (Cur);
55             }
56         }
57     }
58     return false;
59 }
60 
61 int main ()
62 {
63     int t;
64 //    freopen ("test.txt","r",stdin);
65     scanf ("%d",&t);
66     while (t--)
67     {
68         scanf ("%d%d",&m, &n);
69         for (int i=1; i<=m; i++)
70             for (int j=1; j<=n; j++)
71                 scanf (" %c", map[i]+j);
72         scanf ("%d%d%d%d%d",&k, &S.y, &S.x, &E.y, &E.x);
73 
74         puts ((bfs ()?"yes":"no"));
75     }
76     return 0;
77 }
View Code

 BFS代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define N 105
 6 
 7 struct Pos
 8 {
 9     int x, y;
10     int turn;
11 }S, E;
12 char map[N][N];
13 bool used[N][N];
14 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
15 int n, m, k;
16 
17 bool Judge (Pos s)
18 {
19     if (s.x>=1 && s.x<=m && s.y>=1 && s.y<=n && map[s.x][s.y]=='.')
20         return true;
21     return false;
22 }
23 
24 bool  bfs ()
25 {
26     Pos Pre, Cur;
27     queue <Pos> Q;
28     while (!Q.empty ()) Q.pop();
29     memset (used, 0, sizeof used);
30 
31     S.turn = -1;   //第一次不能算作转弯
32     used[S.x][S.y] = true;
33     Q.push (S);
34     while (!Q.empty ())
35     {
36         Pre = Q.front ();
37         Cur = Pre;
38         Q.pop();
39         if (Pre.x == E.x && Pre.y==E.y && Pre.turn<=k)
40           return true;
41         for(int i=0; i<4; i++)
42         {
43             Cur.x = Pre.x + dir[i][0];
44         Cur.y = Pre.y + dir[i][1];
45         while (Judge (Cur))   //每次选定一个方向遍历到底。
46         {
47             if (!used[Cur.x][Cur.y])
48             {
49                 used[Cur.x][Cur.y] = true;
50                 Cur.turn = Pre.turn + 1;
51                 Q.push (Cur);
52                 if (Cur.x == E.x && Cur.y == E.y)
53                 {
54                     if (Cur.turn <= k)
55                         return true;
56                     continue;
57                 }
58             }
59             Cur.x += dir[i][0];
60             Cur.y += dir[i][1];
61         }
62         }
63     }
64     return false;
65 }
66 
67 int main ()
68 {
69     int t;
70     freopen ("test.txt","r",stdin);
71     scanf ("%d",&t);
72     while (t--)
73     {
74         scanf ("%d%d",&m, &n);
75         for (int i=1; i<=m; i++)
76             for (int j=1; j<=n; j++)
77                 scanf (" %c", map[i]+j);
78         scanf ("%d%d%d%d%d",&k, &S.y, &S.x, &E.y, &E.x);
79 
80         puts ((bfs ()?"yes":"no"));
81     }
82     return 0;
83 }
View Code

3.http://poj.org/problem?id=3278

题意:在一条直线上站着一个人 和 一头奶牛,人有三种移动方式(+1 ,-1, *2),问怎么移动可以使移动次数最小就可以到达奶牛的位置;

分析:因为要你求最小的移动步数,即最优解。用 BFS 在一条直线上搜索一遍, 那搜到奶牛时一定会是经过最小的步数。

BFS:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define N 100005
 6 
 7 struct Pos
 8 {
 9     int x;
10     int step;
11 };
12 bool used[N];
13 int n, k;
14 int bfs ()
15 {
16     queue <Pos> Q;
17     while (!Q.empty ()) Q.pop();
18     memset (used, 0, sizeof used);
19 
20     Pos s, cur;
21     s.x = n; s.step = 0;
22     used[s.x] = true;
23     Q.push (s);
24     while (!Q.empty ())
25     {
26         Pos pre = Q.front();
27         Q.pop();
28         for (int i=0; i<3; i++)
29         {
30             if (i==0)
31                 cur.x = pre.x + 1;
32             else if (i==1)
33                 cur.x = pre.x - 1;
34             else
35                 cur.x = pre.x * 2;
36             if (cur.x<0 || cur.x>100000 || used[cur.x])
37                 continue;
38             cur.step = pre.step + 1;
39             if (cur.x == k)
40                 return cur.step;
41             used[cur.x]=true;
42             Q.push (cur);
43         }
44     }
45     return -1;
46 }
47 
48 int main ()
49 {
50     while (~scanf ("%d%d",&n, &k))
51     {
52         if (n > k)
53             printf ("%d
",n-k);
54         else if (n==k)
55             printf ("0
");
56         else
57         printf ("%d
",bfs ());
58     }
59     return 0;
60 }
View Code

4.http://acm.hdu.edu.cn/showproblem.php?pid=1016

题意:给你n个数,n个数围城一个圆环,任何连个相邻的数的都都是素数,输出所有的组合。

分析:题目要求输出所有满足条件的组合, 即所有解。故用DFS可行。和n皇后问题基本一样的。

DFS:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 using namespace std;
 5 
 6 int d[21], n;
 7 int used[21];
 8 bool prime[45];
 9 
10 bool isprime (int n)
11 {
12     int len = sqrt(n);
13     for (int i=2; i<=len; i++)
14         if (n%i==0)
15             return false;
16     return true;
17 }
18 
19 void makeprime ()
20 {
21     memset (prime, 0, sizeof prime);
22     for (int i=2; i<=44; i++)
23         if (isprime(i))
24             prime[i] = true;
25 }
26 void dfs (int cur)
27 {
28     if (cur > n)
29     {
30         if (prime[d[1]+d[n]])
31         {
32             for (int i=1; i<n; i++)
33                 printf ("%d ",d[i]);
34             printf ("%d
",d[n]);
35         }
36         return;
37     }
38     for (int i=2; i<=n; i++)
39     {
40         d[cur] = i;
41         if (!prime[d[cur]+d[cur-1]] || used[i]) continue;
42         used[i] = true;
43         dfs (cur+1);
44         used[i] = false;
45     }
46 }
47 int main ()
48 {
49     int lp=0;
50     makeprime();
51     while (~scanf ("%d",&n))
52     {
53         printf ("Case %d:
",++lp);
54         memset (used, 0, sizeof used);
55         if ((n&1))
56         {
57             puts("");
58             continue;
59         }
60         d[1] = 1;
61         used[1] = true;
62         dfs (2);
63         puts("");
64     }
65     return 0;
66 }
View Code

5.http://acm.hdu.edu.cn/showproblem.php?pid=1241

题意:给你一个矩形,其中‘@’代表油点,孤立的连通油点组成一个油田,问你有多少个油田?

分析:先由两重for循环找到所有的可能的没有被标记的油点, 再由一个DFS/BFS来标记出一个连通的油田,DFS/BFS次数即是油田的次数;

DFS代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define N 105
 5 
 6 char map[N][N];
 7 int dir[][2]={1,0, -1,0, 0,1, 0,-1, 1,1, -1,-1, 1,-1, -1,1};
 8 int n, m, sum;
 9 bool used[N][N];
10 
11 void dfs (int x, int y)
12 {
13     if (x<0||x>n-1 || y<0||y>m-1 || map[x][y]=='*' || used[x][y]) return;
14     used[x][y] = true;
15     for (int i=0; i<8; i++)
16         dfs (x+dir[i][0], y+dir[i][1]);
17 }
18 
19 void Sloved ()
20 {
21     int ans = 0;
22     memset (used, 0, sizeof used);
23     for (int i=0; i<n; i++)
24         for (int j=0; j<m; j++)
25             if (map[i][j]=='@' && !used[i][j])
26             {
27                 ans++;
28                 dfs (i,j);
29             }
30     printf ("%d
",ans);
31 }
32 int main ()
33 {
34     while (~scanf ("%d%d",&n, &m) && n+m)
35     {
36         for (int i=0; i<n; i++)
37             for (int j=0; j<m; j++)
38                 scanf (" %c",map[i]+j);
39 
40         Sloved ();
41     }
42     return 0;
43 }
View Code

BFS代码:有一点点改动,时间竟然还更多了 ………

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define N 105
 6 
 7 struct Pos
 8 {
 9     int x, y;
10 }oil[N*N];
11 char map[N][N];
12 int dir[][2]={1,0, -1,0, 0,1, 0,-1, 1,1, -1,-1, 1,-1, -1,1};
13 int n, m;
14 bool used[N][N];
15 
16 bool judge (Pos s)
17 {
18     if (s.x<0||s.x>n-1 || s.y<0||s.y>m-1 || used[s.x][s.y] || map[s.x][s.y]=='*')
19         return false;
20     return true;
21 }
22 
23 void bfs (Pos a)
24 {
25     queue <Pos> Q;
26 
27     used[a.x][a.y] = true;
28     Q.push (a);
29     while (!Q.empty ())
30     {
31         Pos Pre = Q.front();
32         Q.pop();
33         for (int i=0; i<8; i++)
34         {
35             Pos Cur = Pre;
36             Cur.x += dir[i][0];
37             Cur.y += dir[i][1];
38             if (judge (Cur))
39             {
40                 used[Cur.x][Cur.y] = true;
41                 Q.push (Cur);
42             }
43         }
44     }
45 }
46 int main ()
47 {
48     while (~scanf ("%d%d",&n, &m) && n+m)
49     {
50         int k=0;
51         for (int i=0; i<n; i++)
52             for (int j=0; j<m; j++)
53             {
54                 scanf (" %c",map[i]+j);
55                 if (map[i][j]=='@')
56                 {
57                     oil[k].x = i;
58                     oil[k].y = j;
59                     k++;
60                 }
61             }
62         memset (used, 0, sizeof used);
63         int sum=0;
64         for (int i=0; i<k; i++)
65         {
66             if (used[oil[i].x][oil[i].y])
67                 continue;
68             bfs(oil[i]);
69             sum ++;
70         }
71         printf ("%d
",sum);
72     }
73     return 0;
74 }
View Code

6.http://acm.hdu.edu.cn/showproblem.php?pid=1548

题意:有个奇怪的电梯,里面只有上下两个按钮,并且每层楼都有一个数字Ki,代表可以向上升Ki 层或向下下降Ki 层,要你输出从A层到B层最少需要按按钮的次数,若不可达,则输出-1。

分析:明显,题目是要求最小的按钮次数,即最优解。我们可以用BFS解答。但我们应该可以通过DFS每次选最小的次数来控制最优解获得答案,无奈一直超内存。。

超内存代码:不知为何超内存。}}}}}

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define Min(a, b) (a < b ? a:b)
 5 #define INF 0x3f3f3f3f
 6 
 7 int ans, n, m, a, b, k[205];
 8 bool used[205];
 9 
10 void dfs (int cur, int step)
11 {
12     if (cur == b)
13     {
14         ans = Min (ans, step);
15         return;
16     }
17     for (int i=0; i<2; i++)
18     {
19         int next = cur + (i ? -k[cur]:k[cur]);
20         if (next>n || cur<1) continue; //因为结果老是超内存,故把判断加在此处,但还是超内存
21         if (used[next]) continue;
22         used[next] = true;
23         dfs (next, step+1);
24     }
25 }
26 int main ()
27 {
28     while (~scanf ("%d",&n) && n)
29     {
30         scanf ("%d%d",&a, &b);
31         for (int i=1; i<=n; i++)
32             scanf ("%d",&k[i]);
33 
34         if (a == b)
35         {
36             printf ("0
");
37             continue;
38         }
39         if (a<1||a>n || b<1||b>n)
40         {
41             printf ("-1
");
42             continue;
43         }
44         memset (used, 0, sizeof used);
45         ans = INF;
46         dfs (a, 0);
47         printf ("%d
",ans!=INF ? ans:-1);
48     }
49     return 0;
50 }
View Code

BFS:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define INF 0x3f3f3f3f
 6 
 7 struct Node
 8 {
 9     int floor;
10     int step;
11 }A, B;
12 int n, m, k[205];
13 bool used[205];
14 
15 int bfs ()
16 {
17     queue <Node> Q;
18     Node Pre, Cur;
19     while (!Q.empty ()) Q.pop();
20 
21     memset (used, 0, sizeof used);
22 
23     used[A.floor] = true;
24     A.step = 0;
25     Q.push (A);
26     while (!Q.empty())
27     {
28         Pre = Q.front ();
29         Q.pop();
30         if (Pre.floor == B.floor)
31             return Pre.step;
32 
33         for (int i=0; i<2; i++)
34         {
35             Cur.floor = Pre.floor + (i?-1:1)*k[Pre.floor];
36             Cur.step = Pre.step + 1;
37             if (Cur.floor<1 || Cur.floor>n || used[Cur.floor])
38                 continue;
39             used[Cur.floor] = true;
40             Q.push (Cur);
41         }
42     }
43     return -1;
44 }
45 
46 int main ()
47 {
48     while (~scanf ("%d",&n) && n)
49     {
50         scanf ("%d%d",&A.floor, &B.floor);
51         for (int i=1; i<=n; i++)
52             scanf ("%d",&k[i]);
53         int ans = bfs ();
54         printf ("%d
",ans);
55     }
56     return 0;
57 }
View Code

7.http://acm.hdu.edu.cn/showproblem.php?pid=1253

分析:纯粹的搜索题,只是从二维扩展到三维,增加了两个方向而已;

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define N 55
 6 
 7 struct Pos
 8 {
 9     int x, y, z;
10     int step;
11 };
12 int map[N][N][N], a, b, c, t;
13 bool used[N][N][N];
14 int dir[][3]={0,0,1, 0,0,-1, 1,0,0, -1,0,0, 0,1,0, 0,-1,0};
15 
16 bool judge (Pos cur)
17 {
18     if (cur.x>=0&&cur.x<a && cur.y>=0&&cur.y<b && cur.z>=0&&cur.z<c &&
19          !used[cur.x][cur.y][cur.z] && !map[cur.x][cur.y][cur.z] && cur.step <= t)
20         return true;
21     return false;
22 }
23 
24 int bfs ()
25 {
26     queue <Pos> Q;
27     while (!Q.empty ()) Q.pop();
28     memset (used, 0, sizeof used);
29     Pos Pre, Cur;
30     Pre.x = Pre.y = Pre.z = Pre.step = 0;
31     used[0][0][0] = true;
32     Q.push (Pre);
33     while (!Q.empty ())
34     {
35         Pre = Q.front ();
36         Q.pop();
37         for (int i=0; i<6; i++)
38         {
39             Cur = Pre;
40             Cur.x += dir[i][0];
41             Cur.y += dir[i][1];
42             Cur.z += dir[i][2];
43             Cur.step += 1;
44             if (judge (Cur))
45             {
46                 if (Cur.x==a-1 && Cur.y==b-1 && Cur.z==c-1)
47                     return Cur.step;
48                 used[Cur.x][Cur.y][Cur.z] = true;
49                 Q.push (Cur);
50             }
51         }
52     }
53     return -1;
54 }
55 int main()
56 {
57     int k;
58     scanf ("%d",&k);
59     while (k--)
60     {
61         scanf ("%d%d%d%d",&a, &b, &c, &t);
62         for (int  i=0; i<a; i++)
63             for (int j=0; j<b; j++)
64                 for (int k=0; k<c; k++)
65                     scanf ("%d",&map[i][j][k]);
66         printf ("%d
",bfs());
67     }
68     return 0;
69 }
View Code

DFS代码:我觉得应该是超时还差不多,可是最后变成超内存,我就不知为何了?留着供以后检查。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define N 55
 6 #define INF 0x3f3f3f3f
 7 #define Min(a, b) (a < b ? a : b)
 8 
 9 int map[N][N][N], a, b, c, t, ans;
10 bool used[N][N][N];
11 int dir[][3]={0,0,1, 0,0,-1, 1,0,0, -1,0,0, 0,1,0, 0,-1,0};
12 
13 
14 void dfs (int x, int y, int z, int step)
15 {
16     if (x<0||x>a-1 || y<0||y>b-1 || z<0||z>c-1 || map[x][y][z])
17         return;
18     if (step >= ans || step > t)
19         return;
20     if (x==a-1 && y==b-1 && z==c-1)
21     {
22         ans = Min(ans, step);
23         return;
24     }
25     for (int i=0; i<6; i++)
26     {
27         int xx = x + dir[i][0];
28         int yy = y + dir[i][1];
29         int zz = z + dir[i][2];
30         if (used[xx][yy][zz]) continue;
31 
32         used[xx][yy][zz] = true;
33         dfs (xx, yy, zz, step+1);
34     }
35 }
36 
37 int main()
38 {
39     int k;
40     scanf ("%d",&k);
41     while (k--)
42     {
43         scanf ("%d%d%d%d",&a, &b, &c, &t);
44         for (int  i=0; i<a; i++)
45             for (int j=0; j<b; j++)
46                 for (int k=0; k<c; k++)
47                     scanf ("%d",&map[i][j][k]);
48         ans = INF;
49         memset (used, 0, sizeof used);
50         used[0][0][0] = true;
51         dfs (0, 0, 0, 0);
52         printf ("%d
",ans==INF ? -1:ans);
53     }
54     return 0;
55 }
View Code

8.http://acm.hdu.edu.cn/showproblem.php?pid=1242

题意:公主被魔王抓到地牢里去了,为了防止被人就走,魔王派兵在某些位置守住了,要杀死这些士兵得花费一分钟时间,现在公主的朋友要去救她(题目貌似暗示有很多人去救,可我从‘r'开始搜也能ac , 时间还更优,无语了。。);

分析:纯粹搜索题,让你求最优解,故容易想到用bfs。不过同样的,大多数bfs可以解决的dfs也是可以解决的。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #define N 205
 5 using namespace std;
 6 
 7 struct Pos
 8 {
 9     int x, y; 
10     int step;
11 }S;
12 char map[N][N];
13 bool used[N][N];
14 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
15 int n, m;
16 bool Judge (Pos a)
17 {
18     if (a.x<0||a.x>n-1 || a.y<0||a.y>m-1 || map[a.x][a.y]=='#' || used[a.x][a.y])
19         return false;
20     return true;
21 }
22 
23 int bfs ()
24 {
25     Pos Pre, Cur;
26     queue <Pos> Q;
27     while (!Q.empty ()) Q.pop();
28     memset (used, 0, sizeof used);
29     used[S.x][S.y] = true;
30     Q.push (S);
31     while (!Q.empty ())
32     {
33         Pre = Q.front ();
34         Q.pop();
35         for (int i=0; i<4; i++)
36         {
37             Cur = Pre;
38             Cur.x += dir[i][0];
39             Cur.y += dir[i][1];
40             Cur.step += 1;
41             if (Judge (Cur))
42             {
43                 if (map[Cur.x][Cur.y] == 'r')
44                     return Cur.step;
45                 if (map[Cur.x][Cur.y]=='x')
46                     Cur.step++;
47                 used[Cur.x][Cur.y] = true;
48                 Q.push (Cur);
49             }
50         }
51     }
52     return -1;
53 }
54 int main ()
55 {
56     while (~scanf ("%d%d",&n, &m))
57     {
58         for (int i=0; i<n; i++)
59             for (int j=0; j<m; j++)
60             {
61                 scanf (" %c",map[i]+j);
62                 if (map[i][j] == 'a')
63                     S.x = i, S.y = j;
64             }
65         int ans = bfs ();
66         if (ans == -1)
67             puts ("Poor ANGEL has to stay in the prison all his life.");
68         else
69             printf ("%d
",ans);
70     }
71     return 0;
72 }
View Code

DFS代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #define Min(a, b) (a < b ? a : b)
 5 #define N 205
 6 #define INF 0x3f3f3f3f
 7 using namespace std;
 8 
 9 char map[N][N];
10 bool used[N][N];
11 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
12 int n, m, ans;
13 
14 void dfs (int x, int y, int step)
15 {
16     if (x<0||x>n-1 || y<0||y>m-1 || map[x][y]=='#')
17         return;
18     if(step>=ans)
19         return;
20     if (map[x][y]=='x')
21         step++;
22     if (map[x][y]=='r')
23     {
24         ans = Min(ans, step);
25         return;
26     }
27     for (int i=0; i<4; i++)
28     {
29         int xx = x + dir[i][0];
30         int yy = y + dir[i][1];
31         if (used[xx][yy]) continue;
32         used[xx][yy] = true;
33         dfs (xx, yy, step+1);
34         used[xx][yy] = false;  /////////////////////////////////
35     }
36 }
37 
38 int main ()
39 {
40     int x, y;
41     while (~scanf ("%d%d",&n, &m))
42     {
43         for (int i=0; i<n; i++)
44             for (int j=0; j<m; j++)
45             {
46                 scanf (" %c",map[i]+j);
47                 if (map[i][j] == 'a')
48                     x = i, y = j;
49             }
50 
51         ans = INF;
52         memset (used, 0,sizeof used);
53         used[x][y] = true;
54         dfs (x, y, 0);
55         if (ans == INF)
56             puts ("Poor ANGEL has to stay in the prison all his life.");
57         else
58             printf ("%d
",ans);
59     }
60     return 0;
61 }
View Code

9.http://acm.hdu.edu.cn/showproblem.php?pid=1072

题意:I 做了一个噩梦,他梦到自己在一个迷宫里面,并且身上绑了个初始值是 6 的定时炸弹哥,现在 I 从编号为 2 的位置开始走,并且若在时间不为0之前遇到编号为 4(可以使用任意次) 的位置时,炸弹上的时间可以自动重置为 6,要求输出到达出口(编号为 3 的位置)的最少时间?若不能到达出口,则输出 -1;

分析:一般最优解都趋于用BFS 解答,不过我自己为了练习下 DFS,我分别用 BFS 和 DFS写了两次;

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #define Min(a, b) (a < b ? a : b)
 6 #define INF 0x3f3f3f3f
 7 
 8 const int MAX = 9;
 9 
10 int dir[4][2]={1,0,-1,0,0,1,0,-1};
11 
12 int map[MAX][MAX],dist[MAX][MAX],time[MAX][MAX];
13 int n,m,sx,sy,ans;
14 
15 void dfs (int x, int y, int step, int res)
16 {
17     if (x<0||x>n-1 || y<0||y>m-1 || map[x][y]==0)
18         return;
19     
20     if (res<=0 || step>=ans)
21         return;
22     if (map[x][y]==3)
23     {
24         ans = Min(ans, step);
25         return;
26     }
27     if (map[x][y]==4)
28         res = 6;
29     if (step>=dist[x][y] && time[x][y]>=res)
30         return;
31     dist[x][y] = step;
32     time[x][y] = res;
33 
34     for (int i=0; i<4; i++)
35     {
36         int xx = x + dir[i][0];
37         int yy = y + dir[i][1];
38         
39         dfs (xx, yy, step+1, res-1);
40     }
41 }
42 
43 int main(){
44 
45 //    freopen ("test.txt","r",stdin);
46     int t, x, y;
47     scanf ("%d",&t);
48     while(t--)
49     {
50         scanf ("%d%d",&n, &m);
51         for (int i=0; i<n; i++)
52             for (int j=0; j<m; j++)
53             {
54                 scanf ("%d",map[i]+j);
55                 dist[i][j] = INF;
56                 if (map[i][j]==2)
57                     x = i, y = j;
58             }
59         memset (time, 0, sizeof time);
60         ans = INF;
61         dfs (x, y, 0, 6);
62         printf ("%d
",ans==INF ? -1 : ans);
63     }
64     
65     return 0;
66 }
View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 
 6 struct Pos
 7 {
 8     int x, y;
 9     int res, step, dire;
10 }S, E;
11 int map[15][15], m, n;
12 int used[15][15][4];
13 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
14 
15 bool judge (Pos cur)
16 {
17     if (cur.x<0||cur.x>n-1 || cur.y<0||cur.y>m-1 || map[cur.x][cur.y]==0 || cur.res<=0 || used[cur.x][cur.y][cur.dire]>4)
18         return false;
19     return true;
20 }
21 
22 int bfs ()
23 {
24     Pos Pre, Cur;
25     queue <Pos> Q;
26     while (!Q.empty ()) Q.pop();
27     memset (used, 0, sizeof used);
28     
29     S.step = 0;
30     S.res = 6;
31     S.dire = -1;
32     used[S.x][S.y][S.dire]++;
33     Q.push (S);
34     while (!Q.empty ())
35     {
36         Pre = Q.front ();
37         Q.pop();
38         for (int i=0; i<4; i++)
39         {
40             Cur = Pre;
41             Cur.x += dir[i][0];
42             Cur.y += dir[i][1];
43             Cur.step += 1;
44             Cur.res -= 1;
45             Cur.dire = i;
46             if (judge (Cur))
47             {
48                 if (map[Cur.x][Cur.y]==3)
49                     return Cur.step;
50                 if (map[Cur.x][Cur.y]==4)
51                     Cur.res = 6;
52                 used[Cur.x][Cur.y][Cur.dire]++;
53                 Q.push (Cur);
54             }
55         }
56     }
57     return -1;
58 }
59 int main()
60 {
61     int t;
62 //    freopen ("test.txt","r",stdin);
63     scanf ("%d",&t);
64     while (t--)
65     {
66         scanf ("%d%d",&n, &m);
67         for (int i=0; i<n; i++)
68             for (int j=0; j<m; j++)
69             {
70                 scanf ("%d",map[i]+j);
71                 if (map[i][j] == 2)
72                     S.x = i, S.y = j;
73             }
74         printf ("%d
",bfs());
75     }
76     return 0;
77 }
View Code

10.http://acm.hdu.edu.cn/showproblem.php?pid=2102

分析:同样是一道bfs纯搜索题。只是有个地方需要注意,在传输机#对面还是传输机#的情况,相当于陷入无止境的传输过程中,是不能走的,故把这两个地方当做墙处理。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 
 6 
 7 struct Pos
 8 {
 9     int x, y, z;
10     int step;
11 }S, E;
12 char map[2][15][15];
13 bool used[2][15][15];
14 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
15 int n, m, t;
16 bool bfs ()
17 {
18     Pos Pre, Cur;
19     queue <Pos> Q;
20     while (!Q.empty ()) Q.pop();
21     memset (used, 0, sizeof used);
22 
23     used[S.z][S.x][S.y] = true;
24     Q.push (S);
25     while (!Q.empty ())
26     {
27         Pre = Q.front ();
28         Q.pop();
29         for (int i=0; i<4; i++)
30         {
31             Cur = Pre;
32             Cur.x += dir[i][0];
33             Cur.y += dir[i][1];
34             Cur.step += 1;
35             if (Cur.x>=0 && Cur.x<n && Cur.y>=0 && Cur.y<m && Cur.step<=t)
36             {
37                 if (map[Cur.z][Cur.x][Cur.y]=='#')
38                 {
39                     Cur.z ^= 1;
40                     if (map[Cur.z][Cur.x][Cur.y]=='#')
41                         map[Cur.z][Cur.x][Cur.y] = map[Cur.z^1][Cur.x][Cur.y] = '*';
42                 }
43                 if (map[Cur.z][Cur.x][Cur.y]=='*' || used[Cur.z][Cur.x][Cur.y]) continue;
44                 if (map[Cur.z][Cur.x][Cur.y]=='P')
45                     return true;
46                 used[Cur.z][Cur.x][Cur.y] = true;
47                 Q.push (Cur);
48             }
49         }
50     }
51     return false;
52 }
53 
54 void MakeMap ()
55 {
56     for (int i=0; i<n; i++)
57         for (int j=0; j<m; j++)
58         {
59             scanf (" %c", map[0][i]+j);
60             if (map[0][i][j]=='S')
61             {
62                 S.x = i, S.y = j;
63                 S.z = 0;
64                 S.step = 0;
65             }
66         }
67     for (int i=0;i<n; i++)
68         for (int j=0; j<m; j++)
69         {
70             scanf (" %c",map[1][i]+j);
71             if (map[1][i][j]=='S')
72             {
73                 S.x = i, S.y = j;
74                 S.z = 1;
75                 S.step = 0;
76             }
77         }
78 }
79 
80 int main()
81 {
82     int k;
83     scanf ("%d",&k);
84     while (k--)
85     {
86         scanf ("%d%d%d",&n, &m, &t);
87         
88         MakeMap ();
89 
90         puts (bfs () ? "YES" : "NO");
91 
92     }
93     return 0;
94 }
View Code

我用dfs做了下,杀毒软件一直报错,无法运行。先留着,以后再找bugs。。。。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #define INF 0x3f3f3f3f
 5 #define Min(a, b) (a < b ? a : b)
 6 using namespace std;
 7 
 8 
 9 char map[2][15][15];
10 bool used[2][15][15];
11 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
12 int n, m, t, ans, sx, sy, sz;
13 
14 void dfs (int x, int y, int z, int step)
15 {
16     if (x<0||x>n-1 || y<0||y>m-1 || step>t)
17         return;
18     if (map[z][x][y]=='P')
19     {
20         ans = Min(ans, step);
21         return;
22     }
23     for (int i=0; i<4; i++)
24     {
25         int xx = x + dir[i][0];
26         int yy = y + dir[i][1];
27         if (map[z][xx][yy]=='#')
28         {
29             z ^= 1;
30             if (map[z][xx][yy]=='#')
31                 map[z][xx][yy] = map[z^1][xx][yy] = '*';
32         }
33         if (map[z][xx][yy]=='*' || used[z][xx][yy]) continue;
34 
35         used[z][xx][yy] = true;
36         dfs (xx, yy, z, step+1);
37         used[z][xx][yy] = false;
38     }
39 }
40 
41 void MakeMap ()
42 {
43     for (int i=0; i<n; i++)
44         for (int j=0; j<m; j++)
45         {
46             scanf (" %c", map[0][i]+j);
47             if (map[0][i][j]=='S')
48                 sx = i, sy = j, sz = 0;
49         }
50     for (int i=0;i<n; i++)
51         for (int j=0; j<m; j++)
52         {
53             scanf (" %c",map[1][i]+j);
54             if (map[1][i][j]=='S')
55                 sx = i, sy = j, sz = 1;
56         }
57 }
58 
59 int main()
60 {
61     int k;
62     scanf ("%d",&k);
63     while (k--)
64     {
65         scanf ("%d%d%d",&n, &m, &t);
66         
67         MakeMap ();
68 
69         ans = INF;
70         memset (used, 0, sizeof used);
71         used[sz][sx][sy] = true;
72         dfs (sx, sy, sz, 0);
73 
74         puts (ans!=INF ? "YES" : "NO");
75 
76     }
77     return 0;
78 }
View Code

11.http://acm.hdu.edu.cn/showproblem.php?pid=1175

连连看, 把点(x1 ,y1) 和(X2, y2)连起来,不能乖2次以上的弯;

分析:若用BFS,则搜索到的(X2, y2)时,只能保证最少的步数到达,不能保证转弯次数小于2次、若用DFS搜索时,在搜到(X2, y2)时就可进行全局标记。不过会超时。

错误代码:不知错在哪里-------WA到无爱、、、、

  1 //////错误代码
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 using namespace std;
  6 #define N 1005
  7 
  8 struct Pos
  9 {
 10     int x, y;
 11     int dir, turn;
 12 }S, E;
 13 int map[N][N];
 14 bool used[N][N];
 15 int dire[][2]={1,0, -1,0, 0,1, 0,-1};
 16 int n, m;
 17 
 18 bool bfs ()
 19 {
 20     Pos Pre, Cur;
 21     queue <Pos> Q;
 22     while (!Q.empty ()) Q.pop();
 23     memset (used, 0, sizeof used);
 24 
 25     used[S.x][S.y] = true;
 26     S.turn = 0;
 27     S.dir = -1;
 28     Q.push (S);
 29     while (!Q.empty ())
 30     {
 31         Pre = Q.front ();
 32         Q.pop();
 33         for (int i=0; i<4; i++)
 34         {
 35             Cur = Pre;
 36             Cur.x += dire[i][0];
 37             Cur.y += dire[i][1];
 38             Cur.dir = i;
 39 
 40             if (Cur.dir != Pre.dir && Pre.dir!=-1)
 41                 Cur.turn++;
 42             if (Cur.x<1||Cur.x>n || Cur.y<1||Cur.y>m || Cur.turn > 2) continue;
 43 
 44             if (Cur.x==E.x && Cur.y==E.y)
 45                 return true;
 46             if (map[Cur.x][Cur.y] || used[Cur.x][Cur.y])
 47                 continue;
 48             used[Cur.x][Cur.y] = true;
 49             Q.push (Cur);
 50         }
 51     }
 52     return false;
 53 }
 54 int main ()
 55 {
 56     while (~scanf ("%d%d",&n, &m) && n+m)
 57     {
 58         for (int i=1; i<=n; i++)
 59             for (int j=1; j<=m; j++)
 60                 scanf ("%d",&map[i][j]);
 61 
 62         int t;
 63         scanf ("%d",&t);
 64         while (t--)
 65         {
 66             scanf ("%d%d%d%d",&S.x,&S.y,&E.x,&E.y);
 67 
 68             if (map[S.x][S.y] != map[E.x][E.y] || map[S.x][S.y]==0 || map[E.x][E.y]==0)
 69                 puts ("NO");
 70             else
 71                 puts (bfs ()?"YES":"NO");
 72         }
 73     }
 74     return 0;
 75 }
 76 
 77 
 78 
 79 
 80 ////AC代码;
 81 #include <cstdio>
 82 #include <cstring>
 83 #include <queue>
 84 using namespace std;
 85 #define N 1005
 86 
 87 struct Pos
 88 {
 89     int x, y;
 90     int dir, turn;
 91 }S, E;
 92 int map[N][N];
 93 bool used[N][N];
 94 int dx[]={0, 0, -1, 1};
 95 int dy[]={1, -1, 0, 0};
 96 int n, m;
 97 
 98 bool bfs ()
 99 {
100     Pos Pre, Cur;
101     queue <Pos> Q;
102     while (!Q.empty ()) Q.pop();
103     memset (used, 0, sizeof used);
104 
105     used[S.x][S.y] = true;
106     S.turn = 0;
107     S.dir = -1;
108     Q.push (S);
109     while (!Q.empty ())
110     {
111         Pre = Q.front ();
112         Q.pop();
113         for (int i=0; i<4; i++)
114         {
115             Cur = Pre;
116             Cur.x += dx[i];
117             Cur.y += dy[i];
118             Cur.dir = i;
119             if (Cur.dir != Pre.dir && Pre.dir!=-1)
120                 Cur.turn++;
121             if (Cur.x<1||Cur.x>n || Cur.y<1||Cur.y>m || Cur.turn > 2) continue;
122 
123             if (Cur.x==E.x && Cur.y==E.y)
124                 return true;
125             if (map[Cur.x][Cur.y] || used[Cur.x][Cur.y])
126                 continue;
127             used[Cur.x][Cur.y] = true;
128             Q.push (Cur);
129         }
130     }
131     return false;
132 }
133 int main ()
134 {
135 //    freopen("test.txt","r",stdin);
136     while (~scanf ("%d%d",&n, &m) && n+m)
137     {
138         for (int i=1; i<=n; i++)
139             for (int j=1; j<=m; j++)
140                 scanf ("%d",&map[i][j]);
141 
142         int t;
143         scanf ("%d",&t);
144         while (t--)
145         {
146             scanf ("%d%d%d%d",&S.x,&S.y,&E.x,&E.y);
147 
148             if (map[S.x][S.y] != map[E.x][E.y] || map[S.x][S.y]==0 || map[E.x][E.y]==0)
149                 puts ("NO");
150             else
151                 puts (bfs ()?"YES":"NO");
152         }
153     }
154     return 0;
155 }
View Code

超时代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define N 1005
 5 
 6 int map[N][N], turn[N][N];
 7 bool used[N][N],flag;
 8 int n, m, ex, ey;
 9 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
10 
11 void dfs (int x, int y, int dire, int turn)
12 {
13     if (x<1||x>n || y<1||y>m)
14         return;
15     if (turn > 2 || flag)
16         return;
17     if (x==ex && y==ey)
18     {
19         flag = true;
20         return;
21     }
22     for (int i=0; i<4; i++)
23     {
24         int xx = x + dir[i][0];
25         int yy = y + dir[i][1];
26         if ((xx!=ex || yy!=ey) && map[xx][yy]) continue;
27         if (dire != i && dire != -1)
28             dfs (xx, yy, i, turn+1);
29         else
30             dfs (xx, yy, i, turn);
31     }
32 }
33 int main ()
34 {
35     while (~scanf ("%d%d",&n, &m) && n+m)
36     {
37         for (int i=1; i<=n; i++)
38             for (int j=1; j<=m; j++)
39                 scanf ("%d",map[i]+j);
40         int t, x, y;
41         scanf ("%d,",&t);
42         while (t--)
43         {
44             scanf ("%d%d%d%d",&x, &y, &ex, &ey);
45             if (map[x][y]!=map[ex][ey] || map[x][y]==0 || map[ex][ey]==0)
46                 puts ("NO");
47             else
48             {
49                 flag = false;
50                 dfs (x, y, -1, 0);
51                 puts (flag?"YES":"NO");
52             }
53         }
54     }
55     return 0;
56 }
View Code

12.http://acm.hdu.edu.cn/showproblem.php?pid=1010;

题意:在一个矩形的迷宫里面, 问是否可以恰好在 给定的时间点 走到出口。

‘X':墙壁;

’S':起点;

‘D':出口;

’.': 空地。

这道题,是问你是否有解,不是要求最优解,所以可以用DFS深度搜索,  奇偶性剪枝+路径剪枝优化时间防TLE。如果硬是要用BFS按理来说应该是可以求出结果的,不过我BFS一直WA,一直想不通。留着以后进步了再斟酌。

DFS代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 using namespace std;
 5 
 6 int n, m, t, ex, ey;
 7 char map[10][10];
 8 bool visit[10][10], flag;
 9 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
10 
11 void dfs (int x, int y, int cnt)
12 {
13     if (x<0 || x>n-1 || y<0 || y>m-1) return;
14     if (flag || cnt > t) return;
15     if (x==ex && y==ey)
16     {
17         if (cnt == t)
18             flag = true;
19         return;
20     }
21     for (int i=0; i<4; i++)
22     {
23         int xx = x + dir[i][0];
24         int yy = y + dir[i][1];
25         if (map[xx][yy]=='X' || visit[xx][yy]) continue;
26         visit[xx][yy] = true;
27         dfs (xx, yy, cnt+1);
28         if (flag) return;
29         visit[xx][yy] = false;
30     }
31 }
32 int main ()
33 {
34 //    freopen ("test.txt","r",stdin);
35     while (~scanf ("%d%d%d",&n, &m, &t) && n+m+t)
36     {
37         int wall=0, sx, sy;
38         for (int i=0; i<n; i++)
39             for (int j=0; j<m; j++)
40             {
41                 scanf (" %c",map[i]+j);
42                 if (map[i][j] == 'S')
43                 {
44                     sx = i; sy = j;
45                 }
46                 else if (map[i][j]=='D')
47                 {
48                     ex = i; ey = j;
49                 }
50                 else if (map[i][j]=='X')
51                     wall++;
52             }
53         //路径剪枝
54         if (n*m-wall < t)
55         {
56             puts ("NO");
57             continue;
58         }
59         //奇偶性剪枝
60         int tmp = fabs (sx-ex) + fabs (sy-ey);
61         if ((t - tmp) & 1)
62         {
63             puts ("NO");
64             continue;
65         }
66         memset (visit, 0, sizeof visit);
67         flag = false;
68         visit[sx][sy] = true;
69         dfs(sx, sy, 0);
70         puts ((flag?"YES":"NO"));
71     }
72     return 0;
73 }
View Code

13.http://acm.hdu.edu.cn/showproblem.php?pid=1026

题意:可怜的公主又被魔王给抓去了,被关在一个N*M的二维牢房里,并派了很多不同能力的士兵看守,一个士兵的生命值用 n 表示,表示需要 n 秒才能杀死他。问你一个勇士最少要多久才能救出公主?并输出最少时间,并打印出路线,若不能,则输出”God please help our poor hero.“;

分析:

  求最少时间,我们可以用BFS解决,需要注意的是,遇到士兵的时候要一秒一秒的杀死,然后用时++,不能一秒杀死他,然后一次性加上他的生命值,这样就不能保证求出最优解!!

  我们可以从终点向始点搜,然后每次保存节点前驱到一个二维数组中,然后用队列一次输出即可。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 using namespace std;
  5 #define N 105
  6 
  7 struct Pos
  8 {
  9     int x, y;
 10     int step;
 11 }path[N][N];
 12 
 13 int map[N][N], n, m;
 14 int Map[N][N], ans;
 15 bool used[N][N];
 16 int dir[][2]={1,0, -1,0, 0,1, 0,-1};
 17 
 18 bool Judge (Pos a)
 19 {
 20     if (a.x<0||a.x>n-1 || a.y<0||a.y>m-1 || used[a.x][a.y] || map[a.x][a.y]==-1)
 21         return false;
 22     return true;
 23 }
 24 
 25 int bfs ()
 26 {
 27     queue <Pos> Q;
 28     Pos Pre, Cur;
 29     while (!Q.empty ()) Q.pop();
 30 
 31     memset (used, 0, sizeof used);
 32     used[n-1][m-1] = 0;
 33 
 34     Pre.x = n-1;
 35     Pre.y = m-1;
 36     Pre.step = 0;
 37     
 38     Q.push (Pre);
 39     while (!Q.empty ())
 40     {
 41         Pre = Q.front ();
 42         Q.pop();
 43         if (Pre.x==0 && Pre.y==0)
 44             return Pre.step;
 45         if (map[Pre.x][Pre.y]>=1 && map[Pre.x][Pre.y]<=9)
 46         {
 47             Pre.step++;
 48             map[Pre.x][Pre.y]--;
 49             Q.push (Pre);
 50             continue;
 51         }
 52 
 53         for (int i=0; i<4; i++)
 54         {
 55             Cur = Pre;
 56             Cur.x += dir[i][0];
 57             Cur.y += dir[i][1];
 58             Cur.step += 1;
 59             if (Judge (Cur))
 60             {
 61                 path[Cur.x][Cur.y].x = Pre.x;
 62                 path[Cur.x][Cur.y].y = Pre.y;
 63 
 64                 used[Cur.x][Cur.y] = true;
 65                 Q.push (Cur);
 66             }
 67         }
 68     }
 69     return -1;
 70 }
 71 
 72 void PrintRoad ()
 73 {
 74     Pos Pre;
 75     queue <Pos> Q;
 76     while (!Q.empty ()) Q.pop();
 77     
 78     int x1=0, y1=0, t=1;
 79     int x2, y2;
 80     Pre.x = Pre.y = 0;
 81     Q.push(Pre);
 82     while (1)
 83     {
 84         x2 = x1;
 85         y2 = y1;
 86         Q.push (path[x2][y2]);
 87         x1 = path[x2][y2].x;
 88         y1 = path[x2][y2].y;
 89         if (x1==n-1 && y1==m-1) break;
 90     }
 91 
 92 
 93     while (!Q.empty ())
 94     {
 95         Pre = Q.front ();
 96         Q.pop();
 97         if (Map[Pre.x][Pre.y]>=1 && Map[Pre.x][Pre.y]<=10)
 98         {
 99             int guard = Map[Pre.x][Pre.y];
100             for (int i=0; i<guard; i++)
101                 printf ("%ds:FIGHT AT (%d,%d)
",t++,Pre.x,Pre.y);
102         }
103 
104         if (t==ans+1) break;
105         printf ("%ds:(%d,%d)->(%d,%d)
",t++,Pre.x,Pre.y,path[Pre.x][Pre.y].x,path[Pre.x][Pre.y].y);
106     }
107 }
108 int main()
109 {
110     char c;
111 //    freopen ("test.txt","r",stdin);
112     while (~scanf ("%d%d", &n, &m))
113     {
114         for (int i=0; i<n; i++)
115             for (int j=0; j<m; j++)
116             {
117                 scanf (" %c", &c);
118                 if (c == 'X')
119                     map[i][j] = -1;
120                 else if (c == '.')
121                     map[i][j] = 0;
122                 else if (c>='1' && c<='9')
123                     map[i][j] = c - '0';
124             }
125 
126         memcpy (Map, map, sizeof map);
127 
128         ans = bfs ();
129         if (ans == -1)
130             puts ("God please help our poor hero.");
131         else
132         {
133             printf ("It takes %d seconds to reach the target position, let me show you the way.
", ans);
134             PrintRoad ();
135         }
136         puts ("FINISH");
137     }
138     return 0;
139 }
View Code
原文地址:https://www.cnblogs.com/khan724/p/4050344.html