搜索进阶题

 

1.http://acm.hdu.edu.cn/showproblem.php?pid=1254    推箱子问题

分析:由于箱子每次都只能推,而不能拉,所以我们知道,每次往方向 i 推的时候,人必然会站在一个确切的位置 p 。所以我们在每次推箱子的时候先bfs求出人是否可以到达 p 位置。若可以到达 p ,则往 p 的对面的推动一格,否则判断下一个方向。直到推到目标位置为止。然后我们得到下面的代码:

  1 //First Edit Time:    2014-11-02 17:06

  2 //Last Edit Time:    2014-11-02 18:20

  3 #include <cstdio>

  4 #include <cstring>

  5 #include <queue>

  6 using namespace std;

  7 

  8 struct Pos

  9 {

 10     int bx, by;

 11     int px, py;

 12     int step;

 13 }Box, Person;

 14 

 15 int map[10][10], n, m;

 16 bool used[10][10][10][10];

 17 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

 18 bool visited[10][10];

 19 

 20 bool Judge_Person (Pos a)

 21 {

 22     if(a.px<0 || a.px>m-1 || a.py<0 || a.py>n-1 || visited[a.px][a.py]

 23             || map[a.px][a.py]==1 || (a.px==Box.bx && a.py==Box.by))

 24         return false;

 25     return true;

 26 }

 27 

 28 bool Judge_Box (Pos a)

 29 {

 30     if(a.bx<0 || a.bx>m-1 || a.by<0 || a.by>n-1 || used[a.bx][a.by][Person.px][Person.py] || map[a.bx][a.by]==1)

 31         return false;

 32     return true;

 33 }

 34 

 35 Pos Find_p (Pos a, int i)

 36 {

 37     Pos P = a;

 38     if (i==0)

 39     {

 40         P.px = a.bx + dir[1][0];

 41         P.py = a.by + dir[1][1];

 42     }

 43     else if (i==1)

 44     {

 45         P.px = a.bx + dir[0][0];

 46         P.py = a.by + dir[0][1];

 47     }

 48     else if (i==2)

 49     {

 50         P.px = a.bx + dir[3][0];

 51         P.py = a.by + dir[3][1];

 52     }

 53     else if (i==3)

 54     {

 55         P.px = a.bx + dir[2][0];

 56         P.py = a.by + dir[2][1];

 57     }

 58     return P;

 59 }

 60 

 61 //

 62 bool bfs_person (Pos a)

 63 {

 64     memset (visited, 0, sizeof visited);

 65     if (!Judge_Person (a)) return false;

 66 

 67     Pos Pre, Cur;

 68     queue <Pos> Q;

 69     visited[Person.px][Person.py] = true;

 70 

 71     Q.push (Person);

 72     while (!Q.empty())

 73     {

 74         Pre = Q.front();

 75         Q.pop();

 76         for (int i=0; i<4; i++)

 77         {

 78             Cur.px = Pre.px + dir[i][0];

 79             Cur.py = Pre.py + dir[i][1];

 80             if (Judge_Person (Cur))

 81             {

 82                 visited[Cur.px][Cur.py] = true;

 83                 if (Cur.px==a.px && Cur.py==a.py)

 84                     return true;

 85                 Q.push (Cur);

 86             }

 87         }

 88     }

 89     return false;

 90 }

 91 

 92 int bfs_box ()

 93 {

 94     Pos Pre, Cur, P;

 95     queue <Pos> Q;

 96     memset (used, 0, sizeof used);

 97 

 98     used[Box.bx][Box.by][Person.px][Person.py] = true;

 99     Q.push (Box);

100     while (!Q.empty ())

101     {

102         Pre = Q.front ();

103         Q.pop();

104         for (int i=0; i<4; i++)

105         {

106             Box = Pre;

107 

108             //找到推箱子的位置

109             P = Find_p (Pre, i);

110             

111             if (bfs_person (P))

112             {

113                 Cur = Pre;

114                 Person = P;

115                 Cur.bx += dir[i][0];

116                 Cur.by += dir[i][1];

117                 Cur.step += 1;

118                 if (Judge_Box (Cur))

119                 {

120                     used[Cur.bx][Cur.by][Person.px][Person.py] = true;

121                     if (map[Cur.bx][Cur.by]==3)

122                         return Cur.step;

123                     Q.push (Cur);

124                 }

125             }

126         }

127     }

128     return -1;

129 }

130 

131 int main ()

132 {

133     int t;

134     freopen ("test.in","r",stdin);

135     scanf ("%d",&t);

136     while (t--)

137     {

138         scanf ("%d%d",&m, &n);

139         for (int i=0; i<m; i++)

140             for (int j=0; j<n; j++)

141             {

142                 scanf ("%d",map[i]+j);

143                 if (map[i][j]==2)

144                     Box.bx=i, Box.by=j, Box.step=0;

145                 else if (map[i][j]==4)

146                     Person.px = i,Person.py = j;

147             }

148         int ans = bfs_box ();

149         printf ("%d\n",ans);

150     }

151     return 0;

152 }
View Code

  然后我就这样一直WA到死。后来问了学长才知道,其实我没有考虑到另一种情况:

1
5 3
0 0 0
0 0 0
0 2 0
1 4 1
1 3 1

在上面这种情况下,以上代码得到的答案是-1,因为上面的程序一开始就访问了他本应该去的位置 p ,导致最后要用到 p 的时候得到 p 不可到达的错误信息而是答案出错。

改正之后的代码:

  1 //First Edit Time:    2014-11-02 17:06

  2 //Last Edit Time:    2014-11-02 18:20

  3 #include <cstdio>

  4 #include <cstring>

  5 #include <queue>

  6 using namespace std;

  7 

  8 struct Pos

  9 {

 10     int bx, by;

 11     int px, py;

 12     int step;

 13 }Box, Person;

 14 

 15 int map[10][10], n, m;

 16 bool used[10][10][10][10];

 17 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

 18 bool visited[10][10];

 19 

 20 bool Judge_Person (Pos a)

 21 {

 22     if(a.px<0 || a.px>m-1 || a.py<0 || a.py>n-1 || visited[a.px][a.py]

 23             || map[a.px][a.py]==1 || (a.px==Box.bx && a.py==Box.by))

 24         return false;

 25     return true;

 26 }

 27 

 28 bool Judge_Box (Pos a)

 29 {

 30     if(a.bx<0 || a.bx>m-1 || a.by<0 || a.by>n-1 || used[a.bx][a.by][Person.px][Person.py] || map[a.bx][a.by]==1)

 31         return false;

 32     return true;

 33 }

 34 

 35 Pos Find_p (Pos a, int i)

 36 {

 37     Pos P = a;

 38     if (i==0)

 39     {

 40         P.px = a.bx + dir[1][0];

 41         P.py = a.by + dir[1][1];

 42     }

 43     else if (i==1)

 44     {

 45         P.px = a.bx + dir[0][0];

 46         P.py = a.by + dir[0][1];

 47     }

 48     else if (i==2)

 49     {

 50         P.px = a.bx + dir[3][0];

 51         P.py = a.by + dir[3][1];

 52     }

 53     else if (i==3)

 54     {

 55         P.px = a.bx + dir[2][0];

 56         P.py = a.by + dir[2][1];

 57     }

 58     return P;

 59 }

 60 

 61 //

 62 bool bfs_person (Pos a)

 63 {

 64     memset (visited, 0, sizeof visited);

 65     if (!Judge_Person (a)) return false;

 66     if (a.px==Person.px && a.py==Person.py)  //改正之处。就是把那种情况特判了一下;

 67         return true;

 68     Pos Pre, Cur;

 69     queue <Pos> Q;

 70     visited[Person.px][Person.py] = true;

 71 

 72     Q.push (Person);

 73     while (!Q.empty())

 74     {

 75         Pre = Q.front();

 76         Q.pop();

 77         for (int i=0; i<4; i++)

 78         {

 79             Cur.px = Pre.px + dir[i][0];

 80             Cur.py = Pre.py + dir[i][1];

 81             if (Judge_Person (Cur))

 82             {

 83                 visited[Cur.px][Cur.py] = true;

 84                 if (Cur.px==a.px && Cur.py==a.py)

 85                     return true;

 86                 Q.push (Cur);

 87             }

 88         }

 89     }

 90     return false;

 91 }

 92 

 93 int bfs_box ()

 94 {

 95     Pos Pre, Cur, P;

 96     queue <Pos> Q;

 97     memset (used, 0, sizeof used);

 98 

 99     used[Box.bx][Box.by][Person.px][Person.py] = true;

100     Q.push (Box);

101     while (!Q.empty ())

102     {

103         Pre = Q.front ();

104         Q.pop();

105     //  printf ("Box:(%d, %d) ---- %d\n",Pre.bx+1, Pre.by+1, Pre.step);

106         for (int i=0; i<4; i++)

107         {

108             Box = Pre;

109 

110             //找到推箱子的位置

111             P = Find_p (Pre, i);

112         //    printf ("Person:(%d,%d)\n",P.px+1,P.py+1);

113             if (bfs_person (P))

114             {

115                 Cur = Pre;

116                 Person = P;

117                 Cur.bx += dir[i][0];

118                 Cur.by += dir[i][1];

119                 Cur.step += 1;

120     //        printf ("Goto:(%d, %d)\n",Cur.bx+1, Cur.by+1);

121                 if (Judge_Box (Cur))

122                 {

123                     used[Cur.bx][Cur.by][Person.px][Person.py] = true;

124                     if (map[Cur.bx][Cur.by]==3)

125                         return Cur.step;

126                     Q.push (Cur);

127                 }

128             }

129         }

130     }

131     return -1;

132 }

133 

134 int main ()

135 {

136     int t;

137     freopen ("test.in","r",stdin);

138     scanf ("%d",&t);

139     while (t--)

140     {

141         scanf ("%d%d",&m, &n);

142         for (int i=0; i<m; i++)

143             for (int j=0; j<n; j++)

144             {

145                 scanf ("%d",map[i]+j);

146                 if (map[i][j]==2)

147                     Box.bx=i, Box.by=j, Box.step=0;

148                 else if (map[i][j]==4)

149                     Person.px = i,Person.py = j;

150             }

151         int ans = bfs_box ();

152         printf ("%d\n",ans);

153     }

154     return 0;

155 }
View Code

 

2.http://acm.hdu.edu.cn/showproblem.php?pid=2553       N皇后问题

分析:先明确这是求所有解的问题,所有可以用DFS解答。在N*N的矩阵中,放N个皇后,由于皇后不能在同一行同一列同一斜线,所以,我们单从行来看,在一行中不可能出现两个及以上的皇后。又由于必须得放N个皇后,所以每一行都必有且仅有一个皇后。那么问题的解就可以用一个N元向量 Xi  (i=1,2,3....N)来表示。我们把N个皇后从0--N编号。C[i]表示第 i 行放置的皇后的编号。然后对数轴0--N DFS一遍即可得到答案。为防TLE,先预处理一下。

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <cmath>

 4 using namespace std;

 5 

 6 int C[11], out[11], ans, n;

 7 

 8 void dfs (int cur)

 9 {

10     if (cur==n)

11     {

12         ans++;

13         return;

14     }

15     for (int i=0; i<n; i++)

16     {

17         bool ok = true;

18         C[cur] = i;

19         for (int j=0; j<cur; j++)

20             if (C[cur]==C[j] || cur-j==C[cur]-C[j] || cur+C[cur]==C[j]+j)

21             {

22                 ok = false;break;

23             }

24         if (ok)

25             dfs (cur+1);

26     }

27 }

28 

29 int main ()

30 {

31     for (int i=1; i<=10; i++)

32     {

33         ans = 0;

34         n = i;

35         dfs (0);

36         out[i] = ans;

37     }

38     while (~scanf ("%d",&n) && n)

39         printf ("%d\n",out[n]);

40     return 0;

41 }
View Code

 

3.http://acm.hdu.edu.cn/showproblem.php?pid=2612

题意:Y和M是好朋友,他们两个打算在任一家KFC餐厅(至少有一家kFC餐厅)会面,问你,他们两个总共最少要花费多久时间才能见面?也就是他们两个各自到达这家见面餐厅的时间之和最少是多少?

分析:显然是求最优解无疑,我们首先应该可以确定用BFS求解相比DFS要好点。那么我们可能会想到在输入的时候每次标记出KFC的位子,然后一重循环,分别bfs出Y,M到到第 i 个KFC的时间,每次更新最短时间。但是这种在KFC很多的情况下,复杂度可能会很高而导致TLE。事实上,我们可以用两次BFS求出答案。首先,我们BFS出 Y 到所有KFC的时间,并记录下来。然后,我们再BFS 出 M 到所有kFC的时间,并且在到达KFC时,判断当前 M 的时间加上第一次 BFS Y 到达这个店的时间与最小值的大小关系,选出最小的即可:

代码如下:

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <queue>

 4 using namespace std;

 5 #define N 205

 6 #define INF 0x3f3f3f3f

 7 #define Min(a, b) (a < b ? a : b)

 8 

 9 struct Pos

10 {

11     int x, y;

12     int step;

13 }Y, M;

14 char map[N][N];

15 int used_y[N][N], used_m[N][N];

16 int dir[][2]={1,0, -1,0, 0,1, 0,-1};

17 int n, m;

18 

19 void bfs_y (Pos a)

20 {

21     Pos Pre, Cur;

22     queue <Pos> Q;

23     memset (used_y, 0, sizeof used_y);

24 

25     used_y[a.x][a.y] = 1;

26     Q.push (a);

27     while (!Q.empty ())

28     {

29         Pre = Q.front();

30         Q.pop();

31         if (map[Pre.x][Pre.y]=='@')

32             used_y[Pre.x][Pre.y] = Pre.step;

33         for (int i=0; i<4; i++)

34         {

35             Cur = Pre;

36             Cur.x += dir[i][0];

37             Cur.y += dir[i][1];

38             Cur.step += 1;

39             if (Cur.x<0||Cur.x>n-1 || Cur.y<0||Cur.y>m-1 || used_y[Cur.x][Cur.y] || map[Cur.x][Cur.y]=='#') continue;

40             used_y[Cur.x][Cur.y] = 1;

41             Q.push (Cur);

42         }

43     }

44 }

45 

46 int bfs_m (Pos a)

47 {

48     Pos Pre, Cur;

49     queue <Pos> Q;

50     memset (used_m, 0, sizeof used_m);

51 

52     int ans = INF;

53     used_m[a.x][a.y] = 1;

54     Q.push (a);

55     while (!Q.empty ())

56     {

57         Pre = Q.front();

58         Q.pop();

59         if (map[Pre.x][Pre.y]=='@')

60             ans = Min(ans, (used_y[Pre.x][Pre.y]+Pre.step));

61         for (int i=0; i<4; i++)

62         {

63             Cur = Pre;

64             Cur.x += dir[i][0];

65             Cur.y += dir[i][1];

66             Cur.step += 1;

67             if (Cur.x<0||Cur.x>n-1 || Cur.y<0||Cur.y>m-1 || used_m[Cur.x][Cur.y] || map[Cur.x][Cur.y]=='#') continue;

68             used_m[Cur.x][Cur.y] = 1;

69             Q.push (Cur);

70         }

71     }

72     return ans;

73 }

74 

75 int main()

76 {

77     while (~scanf ("%d%d",&n, &m) && n+m)

78     {

79         for (int i=0; i<n; i++)

80             for (int j=0; j<m; j++)

81             {

82                 scanf (" %c",map[i]+j);

83                 if (map[i][j]=='Y')

84                     Y.x=i, Y.y=j, Y.step=0;

85                 else if (map[i][j]=='M')

86                     M.x=i, M.y=j, M.step=0;

87             }

88 

89         bfs_y (Y);

90         int ans = bfs_m (M);

91         printf ("%d\n",ans*11);

92     }

93     return 0;

94 }
View Code

 

4.http://acm.hdu.edu.cn/showproblem.php?pid=1495   非常可乐

分析:首先BFS求最优解,因为三个杯子之间相互倒水共六种情况:s->n, s->m, n->m, n->s, m->s, m->n;然后遍历六种情况即可,值得注意的是,一个 -= 被我写成+=,WA了N多次。

  1 //First Edit Time:    2014-11-05 20:54

  2 //Last Edit Time:    2014-11-05 20:55

  3 #include <cstdio>

  4 #include <cstring>

  5 #include <queue>

  6 #define N 110

  7 using namespace std;

  8 

  9 struct Node

 10 {

 11     int x, y;

 12     int cup, step;

 13 };

 14 int s, n, m;

 15 bool used[N][N][N];

 16 

 17 void Move (Node &a, int i)

 18 {

 19     // 倒出的水取决于 Min(当前杯中剩余容量, 最多能倒出的水量)

 20     if (i==0)  //s -> x

 21     {

 22         int tmp = (n-a.x) < a.cup ? (n-a.x):a.cup;

 23         a.x += tmp;

 24         a.cup -= tmp;

 25     }

 26     else if (i==1) // s -> y

 27     {

 28         int tmp = (m-a.y) < a.cup ? (m-a.y):a.cup;

 29         a.y += tmp;

 30         a.cup -= tmp;

 31     }

 32     else if (i==2) // x -> s

 33     {

 34         int tmp =  (s-a.cup) < a.x ? (s-a.cup):a.x;

 35         a.cup += tmp;

 36         a.x -= tmp;

 37     }

 38     else if (i==3)  // y -> s

 39     {

 40         int tmp = (s-a.cup) < a.y ? (s-a.cup):a.y;

 41         a.cup += tmp;

 42         a.y -= tmp;

 43     }

 44     else if (i==4) // y -> x

 45     {

 46         int tmp = (n-a.x) < a.y ? (n-a.x) : a.y;

 47         a.x += tmp;

 48         a.y -= tmp;

 49     }

 50     else if (i==5)  // x -> y

 51     {

 52         int tmp = (m-a.y) < a.x ? (m-a.y) : a.x;

 53         a.y +=  tmp;

 54         a.x -= tmp;         //   -= 被写成 += wa无数,我也是醉了、

 55     }

 56 }

 57 

 58 int bfs ()

 59 {

 60     Node Pre, Cur;

 61     queue <Node> Q;

 62     memset (used, 0, sizeof used);

 63 

 64     used[s][0][0] = true;

 65     Pre.x=Pre.y=Pre.step = 0;

 66     Pre.cup = s;

 67     Q.push (Pre);

 68     while (!Q.empty())

 69     {

 70         Pre = Q.front();

 71         Q.pop();

 72      // printf ("(%d, %d, %d) ----- %d\n",Pre.cup, Pre.x, Pre.y, Pre.step);

 73         if ((Pre.x==Pre.y && Pre.x+Pre.y==s)||(Pre.x==Pre.cup && Pre.x+Pre.cup==s) || (Pre.cup==Pre.y && Pre.cup+Pre.y==s))

 74             return Pre.step;

 75         for (int i=0; i<6; i++)

 76         {

 77             Cur = Pre;

 78             Move (Cur, i);

 79             Cur.step += 1;

 80     //    printf ("(%d, %d, %d)\n",Cur.cup, Cur.x, Cur.y);

 81             if (!used[Cur.cup][Cur.x][Cur.y])

 82             {

 83                 used[Cur.cup][Cur.x][Cur.y] = true;

 84                 Q.push (Cur);

 85             }

 86         }

 87     }

 88     return -1;

 89 }

 90 int main ()

 91 {

 92     while (~scanf ("%d%d%d",&s, &n, &m) && s+n+m)

 93     {

 94       int ans;

 95       if (s&1) ans = -1;else ans = bfs ();

 96 

 97         if (ans == -1)

 98             puts ("NO");

 99         else

100             printf("%d\n",ans);

101     }

102     return 0;

103 }
View Code

 

你可能感兴趣的:(搜索)