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 }

 

转载于:https://www.cnblogs.com/zxotl/archive/2013/01/22/2871653.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值