首页 > 代码库 > 搜索进阶题

搜索进阶题

 

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

 

搜索进阶题