广搜+位运算:
在这里我们建立一个2进制钥匙串,如果对应位有钥匙则该位为1,反之为0,每当遇见钥匙,我们就把这把这把钥匙加到钥匙串的对应位置,广搜压栈的时候需要判断该位置是否为门的位置,并且检查是否有相应的钥匙,并且每个点对应一个钥匙串的状态,建立三维数组,前两位表示保存点的位置,后一位表示相应位置对应的钥匙的状态,进行一遍bfs即可。
#include<stdio.h>
int m,n,t;
char map[21][21];
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int find[21][21][1025];
int f[10000],a[10000],b[10000],bsu[10000];
int start_x,start_y,end_x,end_y;
int bfs(int x,int y)
{
a[1]=x;
b[1]=y;
f[1]=0;
bsu[1]=0;
int front=1;
int rear=1;
find[x][y][0]=1;
while(front<=rear)
{
for(int i=0;i<4;i++)
{
int j,k;
int xx=a[front]+dir_x[i];
int yy=b[front]+dir_y[i];
if('a'<=map[xx][yy]&&map[xx][yy]<='j')
{
if((f[front]>>(map[xx][yy]-'a'))%2==0) //把钥匙放到钥匙串的对应位置
j=f[front]^(1<<(map[xx][yy]-'a')) ;
else
j=f[front];
}
else
j=f[front];
if('A'<=map[xx][yy]&&map[xx][yy]<='J')
{
if((f[front]>>(map[xx][yy]-'A'))%2==1) //检查当前钥匙串中是否存在一把钥匙能把这把锁打开
k=1;
else
k=0;
}
else
k=1;
if(1<=xx&&xx<=m&&1<=yy&&yy<=n&&map[xx][yy]!='*'&&k==1)
if(find[xx][yy][1024]==0||(find[xx][yy][1024]==1&&find[xx][yy][j]==0))
{
rear++;
bsu[rear]=bsu[front]+1;
if(bsu[rear]>=t) return -1;
if(xx==end_x&&yy==end_y) return bsu[rear];
a[rear]=xx;
b[rear]=yy;
find[xx][yy][1024]=1;
find[xx][yy][j]=1;
f[rear]=j;
}
}
front++;
}
return -1;
}
int main()
{
while(scanf("%d%d%d",&m,&n,&t)!=EOF)
{
getchar();
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%c",&map[i][j]);
find[i][j][1024]=0;
if(map[i][j]=='@')
{
start_x=i;
start_y=j;
}
if(map[i][j]=='^')
{
end_x=i;
end_y=j;
}
for(int k=0;k<=1023;k++)
find[i][j][k]=0;
}
getchar();
}
printf("%d\n",bfs(start_x,start_y));
}
return 0;
}
hdu 1429 胜利大逃亡(续)
最新推荐文章于 2022-03-12 11:46:02 发布