2014 ACM/ICPC Asia Regional Guangzhou Online
N*N矩阵 M个钥匙
K起点,T终点,S点需多花费1点且只需要一次,1-9表示9把钥匙,只有当前有I号钥匙才能拿I+1号钥匙,可以不拿钥匙只从上面走过
4维数组判重,第三维表示钥匙已经拿到第几把,第四维表示已经走过的S的状况,用状压存储
#include "stdio.h"
#include "string.h"
#include "queue"
using namespace std;
int inf=0x3f;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int b[10];
int n,m,s_x,s_y;
int hash[110][110][10][60];
char str[110][110];
struct node
{
int x,y,step,status,key;
friend bool operator<(node n1,node n2)
{
return n1.step>n2.step;
}
};
int bfs()
{
priority_queue<node>q;
node cur,next;
int i,snk;
cur.x=s_x;
cur.y=s_y;
cur.step=0;
cur.status=0; // 已走过S的情况
cur.key=0; // 当前钥匙
q.push(cur);
str[s_x][s_y]='.';
memset(hash,inf,sizeof(hash));
hash[cur.x][cur.y][0][0]=0;
while (!q.empty())
{
cur=q.top();
q.pop();
if (str[cur.x][cur.y]=='T' && cur.key==m) return cur.step;
for (i=0; i<4; i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if (next.x<0 || next.x>=n || next.y<0 || next.y>=n) continue;
if (str[next.x][next.y]=='#') continue;
if (str[next.x][next.y]=='.' || str[next.x][next.y]=='T')
{
next.step=cur.step+1;
next.key=cur.key;
next.status=cur.status;
}
if (str[next.x][next.y]<='9' && str[next.x][next.y]>='1')
{
if (str[next.x][next.y]-'0'==cur.key+1)
next.key=cur.key+1;
else
next.key=cur.key;
next.status=cur.status;
next.step=cur.step+1;
}
if (str[next.x][next.y]<='e' && str[next.x][next.y]>='a')
{
snk=b[str[next.x][next.y]-'a'];
if ((cur.status & snk)==snk)
{
next.status=cur.status;
next.step=cur.step+1;
next.key=cur.key;
}
else
{
next.status=cur.status|snk;
next.step=cur.step+2;
next.key=cur.key;
}
}
if (hash[next.x][next.y][next.key][next.status]>next.step)
{
q.push(next);
hash[next.x][next.y][next.key][next.status]=next.step;
}
}
}
return -1;
}
int main()
{
int i,j,ans,cnt;
b[0]=1;
for (i=1; i<=5; i++)
b[i]=b[i-1]*2;
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n==0 && m==0) break;
getchar();
for (i=0; i<n; i++)
gets(str[i]);
cnt=0;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{
if (str[i][j]=='K')
{
s_x=i;
s_y=j;
}
if (str[i][j]=='S')
{
str[i][j]='a'+cnt;
cnt++;
}
}
ans=bfs();
if (ans==-1) printf("impossible\n");
else printf("%d\n",ans);
}
return 0;
}