胜利大逃亡(续)(bfs+状态压缩)
胜利大逃亡(续) |
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) |
Total Submission(s): 85 Accepted Submission(s): 55 |
Problem Description
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……
这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。 |
Input
每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:
. 代表路 * 代表墙 @ 代表Ignatius的起始位置 ^ 代表地牢的出口 A-J 代表带锁的门,对应的钥匙分别为a-j a-j 代表钥匙,对应的门分别为A-J 每组测试数据之间有一个空行。 |
Output
针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。
|
Sample Input
4 5 17 @A.B. a*.*. *..*^ c..b* 4 5 16 @A.B. a*.*. *..*^ c..b* |
Sample Output
16 -1 |
Author
LL
|
Source
ACM暑期集训队练习赛(三)
|
Recommend
linle
|
/* 题意:略 初步思路:这个题想了很久,钥匙的问题的没有办法解决,看了一下题解,才知道,搜索的状态在加一维就是压缩后的钥匙的状态, 因为钥匙的数量不是很多,所以可以状态压缩一下来表示。 */ #include<bits/stdc++.h> using namespace std; int dir[4][2]={1,0,-1,0,0,1,0,-1}; bool vis[22][22][(1<<11)];//用来标记走到i,j这个并且钥匙压缩完之后的状态是k的状态 char mapn[22][22];//地图 int sx,sy;//初始位置 int n,m,t; struct node{ int x,y,step,state; node(){} node(int a,int b,int c,int d){ x=a; y=b; step=c; state=d; } }; bool ok(int x,int y){//坐标状态是不是合法 if(x<0||x>=n||y<0||y>=m||mapn[x][y]=='*') return false; return true; } bool judge(int x,int y,int state){//判断一下这种状态是不是能通过这扇门 int res=mapn[x][y]-'A'; if(((1<<res)&state)==0) return false; return true; } int bfs(){ memset(vis,0,sizeof vis); node Next,start; queue<node>q; q.push(node(sx,sy,0,0)); vis[sx][sy][0]=1; while(!q.empty()){ start=q.front(); q.pop(); // cout<<start.x<<" "<<start.y<<" "<<start.state<<endl; if(start.step>=t){ return -1; } if(mapn[start.x][start.y]=='^'){ return start.step; } for(int i=0;i<4;i++){ Next=start; Next.x+=dir[i][0]; Next.y+=dir[i][1]; Next.step++;//走了一步了 if(ok(Next.x,Next.y)==false)//出界了 continue; if(mapn[Next.x][Next.y]>='A'&&mapn[Next.x][Next.y]<='Z'&&judge(Next.x,Next.y,Next.state)==false){//遇到门没有钥匙 // cout<<Next.x<<" "<<Next.y<<" "<<Next.state<<endl; continue; } if(mapn[Next.x][Next.y]>='a'&&mapn[Next.x][Next.y]<='z'){//遇到钥匙 int res=mapn[Next.x][Next.y]-'a'; // cout<<"钥 匙="<<res<<endl; // cout<<"状 态="<<Next.state<<endl; Next.state=((1<<res)|Next.state); // cout<<"事后状态="<<Next.state<<endl; } if(vis[Next.x][Next.y][Next.state]==1)//这个状态走过了 continue; vis[Next.x][Next.y][Next.state]=1; q.push(Next); } } return -1; } int main(){ // freopen("in.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&t)!=EOF){ for(int i=0;i<n;i++){ scanf("%s",&mapn[i]); for(int j=0;j<m;j++){ if(mapn[i][j]=='@') sx=i,sy=j; } } printf("%d\n",bfs()); } return 0; }
我每天都在努力,只是想证明我是认真的活着.