Appoint description:
Description
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……
这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,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
每组测试数据之间有一个空行。
. 代表路
* 代表墙
@ 代表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
思路:
这题一开始认为是直接求出钥匙与门之间的距离就能人走到门那里直接加刚刚求出的距离,就OK了。结果写好才发现根本思路是错的,而且代码非常复杂,两个结构体,3,4个函数。最后看了看题解,都说是增加钥匙状态去当标记,这样就能走重复过的x,y了,巧妙。最后wa了两次,因为不记得比较第几把钥匙Wa了。
总结:
之前是想用容器去将钥匙的情况的存储起来结果发现复杂度太高了,而且不能保证能全部遍历一次, 所以做了这题后,我发现其实增加维数在搜索里就是一种暴力求解的工具。
AC代码:
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<cstdio>
#include<map>
using namespace std;
#define T 1000005
int n,m,t;
char str[30][30];
bool vis[30][30][1<<11];
int fx[][2] = {{1,0},{0,1},{-1,0},{0,-1}};
bool jugde(int x,int y,int& key)
{
if(x>=0&&x<n&&y>=0&&y<m&&str[x][y]!='*'&&!vis[x][y][key]){
if(str[x][y]>='a'&&str[x][y]<='z'){
key|= (1<<(str[x][y]-'a'));
return true;
}
else if(str[x][y]=='.'||str[x][y]>='A'&&str[x][y]<='Z'&&((key>>(str[x][y]-'A'))&1))
return true;
else if(str[x][y]=='@'){
return true;
}
}
return false;
}
struct point
{
int x,y,key,cnt;
point(int _x,int _y,int _cnt,int _key):x(_x),y(_y),cnt(_cnt),key(_key){}
point(){}
}p[T],q;
int bfs(int x,int y,int xx,int yy)
{
int head=0,tail=0;
int i,tx,ty,key;
p[tail].key = 0;
p[tail].x = x,p[tail].y = y,p[tail++].cnt = 0;
vis[x][y][0] = true;
while(head<tail)
{
q = p[head++];
for(i=0;i<4;++i){
tx = q.x + fx[i][0];
ty = q.y + fx[i][1];
key = q.key;
if(tx==xx&&ty==yy){
return q.cnt+1;
}
int key1 = key;
if(jugde(tx,ty,key)){
if(key!=key1)vis[tx][ty][key1] = true;
vis[tx][ty][key] = true;
p[tail++] = point(tx,ty,q.cnt+1,key);
}
}
}
return -1;
}
void Init()
{
memset(vis,false,sizeof(vis));
}
int main()
{
#ifdef zsc
freopen("input.txt","r",stdin);
#endif
int x,y,i,k;
int xn,yn;
while(~scanf("%d%d%d",&n,&m,&t))
{
memset(vis,false,sizeof(vis));
for(i=0;i<n;++i){
for(k=0;k<m;++k){
scanf("\n%c",&str[i][k]);
if(str[i][k]=='@'){
x = i,y=k;
}
if(str[i][k]=='^'){
xn=i,yn=k;
}
}
}
int tmp = bfs(x,y,xn,yn);
if(tmp<t&&tmp!=-1){
printf("%d\n",tmp);
}
else
{
printf("-1\n");
}
}
return 0;
}