搜索基础题

 

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",n-k);

54         else if (n==k)

55             printf ("0\n");

56         else

57         printf ("%d\n",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\n",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:\n",++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\n",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\n",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\n");

37             continue;

38         }

39         if (a<1||a>n || b<1||b>n)

40         {

41             printf ("-1\n");

42             continue;

43         }

44         memset (used, 0, sizeof used);

45         ans = INF;

46         dfs (a, 0);

47         printf ("%d\n",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\n",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\n",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\n",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\n",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\n",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\n",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\n",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)\n",t++,Pre.x,Pre.y);

102         }

103 

104         if (t==ans+1) break;

105         printf ("%ds:(%d,%d)->(%d,%d)\n",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.\n", ans);

134             PrintRoad ();

135         }

136         puts ("FINISH");

137     }

138     return 0;

139 }
View Code

 

你可能感兴趣的:(基础)