Maze

Maze

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5094

BFS+状态压缩

把身上携带钥匙的状态压缩成一个2^10的整数。这道题难在如何表示墙和门所在的位置,我是另开了个两个N*N的数组mp_r[N][N],mp_c[N][N]分别以行和列错位存储存储墙和门的位置(mp_r[i][j]表示第r行j列和第r行j+1列的墙的状态),其他人好像是用mp[N][N][4]来存储墙和门的状态的,突然觉得我好蠢...这题坑点是一个位置可以存多把钥匙(吐血 怪不得这么多次都是WA)= =

代码如下:

  1 #include<cstdio>
  2 #include<queue>
  3 #include<cstring>
  4 #define LL long long
  5 #define N 55
  6 using namespace std;
  7 struct node{
  8     LL x,y,time;
  9     bool key[10];
 10 };
 11 node s,e;
 12 LL mp_r[N][N];
 13 LL mp_c[N][N];
 14 LL key[N][N][10];
 15 LL n,m,p;
 16 bool mark[1024][N][N];
 17 bool flag;
 18 LL dx[]={-1,1,0,0};
 19 LL dy[]={0,0,-1,1};
 20 LL zip(node t){
 21     LL code=0;
 22     for(LL i=0;i<p;++i)
 23         code=(code<<1)|t.key[i];
 24     return code;
 25 }
 26 void init(){
 27     flag=0;
 28     s.x=1,s.y=1,s.time=0;
 29     e.x=n,e.y=m,e.time=0;
 30     memset(mp_r,-1,sizeof(mp_r));
 31     memset(mp_c,-1,sizeof(mp_c));
 32     memset(key,0,sizeof(key));
 33     memset(mark,0,sizeof(mark));
 34     mark[0][1][1]=1;
 35     LL k;
 36     scanf("%I64d",&k);
 37     while(k--){
 38         LL x1,y1,x2,y2,g;
 39         scanf("%I64d%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2,&g);
 40         if(x1-x2==0)mp_r[x1][(y1+y2)/2]=g;
 41         else mp_c[(x1+x2)/2][y1]=g;
 42     }
 43     scanf("%I64d",&k);
 44     while(k--){
 45         LL x,y,q;
 46         scanf("%I64d%I64d%I64d",&x,&y,&q);
 47         q--;
 48         key[x][y][q]=1;
 49     }
 50     for(int i=0;i<10;i++)
 51     if(key[1][1][i])s.key[i]=1;
 52 }
 53 int main(void){
 54     while(~scanf("%I64d%I64d%I64d",&n,&m,&p)){
 55         init();
 56         queue<node> que;
 57         que.push(s);
 58         while(!que.empty()){
 59             node t=que.front();
 60             que.pop();
 61             if(t.x==e.x&&t.y==e.y){
 62                 e.time=t.time;
 63                 flag=1;
 64                 break;
 65             }
 66             for(LL i=0;i<4;++i){
 67                 LL x=t.x+dx[i];
 68                 LL y=t.y+dy[i];
 69                 if(1<=x&&x<=n&&1<=y&&y<=m){
 70                     node temp;
 71                     temp.x=x,temp.y=y,temp.time=t.time+1;
 72                     for(LL j=0;j<p;++j)temp.key[j]=t.key[j];
 73                     for(int j=0;j<10;j++)
 74                         if(key[x][y][j])temp.key[j]=1;
 75                     if(dx[i]){
 76                         if(mp_c[(x+t.x)/2][y]!=0)
 77                         if(mp_c[(x+t.x)/2][y]==-1||temp.key[mp_c[(x+t.x)/2][y]-1]){
 78                             LL key_zip=zip(temp);
 79                             if(!mark[key_zip][x][y]){
 80                                 mark[key_zip][x][y]=1;
 81                                 que.push(temp);
 82                             }
 83                         }
 84                     }else if(dy[i]){
 85                         if(mp_r[x][(y+t.y)/2]!=0)
 86                         if(mp_r[x][(y+t.y)/2]==-1||temp.key[mp_r[x][(y+t.y)/2]-1]){
 87                             LL key_zip=zip(temp);
 88                             if(!mark[key_zip][x][y]){
 89                                 mark[key_zip][x][y]=1;
 90                                 que.push(temp);
 91                             }
 92                         }
 93                     }
 94                 }
 95             }
 96         }
 97         if(flag)printf("%I64d\n",e.time);
 98         else printf("-1\n");
 99     }
100 }

 

转载于:https://www.cnblogs.com/barrier/p/5796877.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值