HDU ACM 1254 推箱子 (两层广搜 + 位运算标记)
http://acm.hdu.edu.cn/showproblem.php?pid=1254
题意:把箱子推进坑。。。
思路:用广搜遍历箱子的四个方向,由于要由人推箱子 人要到箱子后面推。
所以要再用一次广搜,判断人能不能走到箱子后面。(在广搜里面嵌套广搜)
由于向四个方向移动,人和箱子的相对位置是不一样的所以要分别记录四次。
我用的是used[][]数组的值来标记。二进制哈希,上下左右四个方向用4位来标记。
每次仅判断相应的方向是否被使用过。
1 void markused(Node a,int i){//标记某一方向为用过 2 int x = 1<<i; 3 visit[a.x][a.y] = visit[a.x][a.y] | x; 4 }
1 int isused(Node a,int i){//判断该方向有没有被标记为用过 2 int x = visit[a.x][a.y]; 3 x = x>>i; 4 return x & 1; 5 }
1 #include <iostream> 2 #include <queue> 3 using namespace std; 4 struct Node{ 5 int x; 6 int y; 7 int step; 8 }; 9 int point[4][2] = {0,-1,0,1,-1,0,1,0};//左 右 上 下 10 int map[10][10]; 11 bool used[10][10]; 12 int visit[10][10]; 13 int n,m; 14 Node s,e; 15 Node sman; 16 Node eman; 17 18 int judge_way(int i){//得到箱子后面位置的方向 19 int j; 20 if(i%2 == 1){ 21 j = i-1; 22 } 23 else{ 24 j = i+1; 25 } 26 return j; 27 } 28 bool judge(Node a,int i){//判断能不能移动到箱子后面 29 int j; 30 j = judge_way(i); 31 a.x = a.x + point[j][0]; 32 a.y = a.y + point[j][1]; 33 if(map[a.x][a.y] != 1){ 34 return 1; 35 } 36 return 0; 37 } 38 int isused(Node a,int i){//判断该方向有没有被标记为用过 39 int x = visit[a.x][a.y]; 40 x = x>>i; 41 return x & 1; 42 } 43 void markused(Node a,int i){//标记某一方向为用过 44 int x = 1<<i; 45 visit[a.x][a.y] = visit[a.x][a.y] | x; 46 } 47 int man_BFS(Node begin,Node ends,Node box){//对人的广搜 48 queue <Node> q; 49 memset(used,0,sizeof(used)); 50 q.push(begin); 51 used[begin.x][begin.y] = 1; 52 while(!q.empty()){ 53 Node mid = q.front(); 54 q.pop(); 55 if(mid.x == ends.x && mid.y == ends.y){ 56 return 1; 57 } 58 int i; 59 for(i=0;i<4;i++){ 60 Node ans; 61 ans.x = mid.x + point[i][0]; 62 ans.y = mid.y + point[i][1]; 63 if(!used[ans.x][ans.y] && map[ans.x][ans.y] != 1 && !(ans.x == box.x && ans.y == box.y)){ 64 used[ans.x][ans.y] = 1; 65 q.push(ans); 66 } 67 } 68 } 69 return 0; 70 } 71 int BFS(){//对箱子的广搜 72 if(s.x == e.x && s.y == e.y){ 73 return 0; 74 } 75 memset(visit,0,sizeof(visit)); 76 queue <Node> q; 77 queue <Node> qman; 78 q.push(s); 79 qman.push(sman); 80 while(!q.empty()){ 81 Node mid = q.front(); 82 q.pop(); 83 Node sman = qman.front(); 84 qman.pop(); 85 mid.step++; 86 int i; 87 for(i=0;i<4;i++){ 88 Node ans; 89 ans.x = mid.x + point[i][0]; 90 ans.y = mid.y + point[i][1]; 91 ans.step = mid.step; 92 if(!isused(ans,i) && map[ans.x][ans.y] != 1 && judge(mid,i)){ 93 int j; 94 j = judge_way(i); 95 eman.x = mid.x + point[j][0]; 96 eman.y = mid.y + point[j][1]; 97 if(man_BFS(sman,eman,mid)){ 98 if(ans.x == e.x && ans.y == e.y){ 99 return mid.step; 100 } 101 markused(ans,i); 102 q.push(ans); 103 qman.push(mid); 104 } 105 } 106 } 107 } 108 return -1; 109 } 110 int main(){ 111 int T; 112 cin>>T; 113 while(T--){ 114 memset(map,0,sizeof(map)); 115 cin>>m>>n; 116 int i,j; 117 for(i=0;i<=m+1;i++){//加一圈,方便判断 118 map[i][0] = 1; 119 map[i][n+1] = 1; 120 } 121 for(i=0;i<=n+1;i++){ 122 map[0][i] = 1; 123 map[m+1][i] = 1; 124 } 125 126 127 for(i=1;i<=m;i++){ 128 for(j=1;j<=n;j++){ 129 cin>>map[i][j]; 130 if(map[i][j] == 2){ 131 s.x = i; 132 s.y = j; 133 s.step = 0; 134 map[i][j]=0; 135 } 136 if(map[i][j] == 3){ 137 e.x = i; 138 e.y = j; 139 e.step = 0; 140 map[i][j]=0; 141 } 142 if(map[i][j] == 4){ 143 sman.x = i; 144 sman.y = j; 145 sman.step = 0; 146 map[i][j]=0; 147 } 148 } 149 } 150 cout<<BFS()<<endl; 151 } 152 return 0; 153 }