一开始用dfs果断超时,贴上超时代码:
<span style="font-size:18px;">#include <stdio.h>
#include <iostream>
#include <string.h>
#define MAX 0xffffff
int m,n,flag,tt,sx,sy;
char key[]={'y','g','r','b'};
char door[]={'Y','G','R','B'};
int dirx[]={0,1,0,-1},diry[]={1,0,-1,0};
char maze[105][105];
bool mark[105][105][22];
void dfs(int x,int y,int t,int k)
{
if(flag)
return ;
if(maze[x][y]=='X')
{
tt=t;
flag=1;
return ;
}
if(x<0 || x>=n || y<0 || y>=m || maze[x][y]=='#' || mark[x][y][k])
return ;
if(isupper(maze[x][y]) && maze[x][y]!='X') //це
{
for(int i=0;i<=4;i++)
if(maze[x][y]==door[i])
{
if((k&(1<<i))==0)
return ;
}
}
else if(islower(maze[x][y])) //т©Ёв
{
for(int i=0;i<=4;i++)
if(maze[x][y]==key[i])
{
k|=(1<<i);
break;
}
}
for(int i=0;i<4;i++)
{
int fx=x+dirx[i];
int fy=y+diry[i];
mark[x][y][k]=true;
dfs(fx,fy,t+1,k);
mark[x][y][k]=false;
}
}
int main()
{
while(scanf("%d %d",&n,&m) &&(m || n))
{
memset(mark,0,sizeof(mark));
flag=0;
tt=-1;
for(int i=0;i<n;i++)
{
scanf("%s",maze[i]);
for(int j=0;j<m;j++)
if(maze[i][j]=='*')
sx=i,sy=j;
}
dfs(sx,sy,0,0);
if(tt!=-1)
printf("Escape possible in %d steps.\n",tt);
else
printf("The poor student is trapped!\n");
}
return 0;
}
</span>
bfs+状态压缩
这题和普通的迷宫不一样的是多了4种钥匙以及对应的门
开一个三维数组mark[x][y][k]用来存各个位置的各种状态,通俗的说就是,判断在"k"这种状态下,x,y这个位置是否走过。
用二进制存得到钥匙的状态,用4位即可。
上代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
typedef struct ac
{
int x,y,t;
int k; //用二进制存4把钥匙
}node;
int dirx[]={0,1,0,-1},diry[]={1,0,-1,0};
bool mark[105][105][20]; //判断在有不同的key的各个位置是否出现过
int m,n;
char key[]={'b','g','y','r'};
char door[]={'B','G','Y','R'};
char maze[105][105];
void bfs(node s)
{
queue <node> q;
mark[s.x][s.y][s.k]=true;
q.push(s);
while(!q.empty())
{
node r=q.front();
q.pop();
if(maze[r.x][r.y]=='X')
{
printf("Escape possible in %d steps.\n",r.t);
return ;
}
for(int i=0;i<4;i++)
{
node w=r;
w.x+=dirx[i];
w.y+=diry[i];
w.t++;
if(w.x<0 || w.x>=n || w.y<0 || w.y>=m || maze[w.x][w.y]=='#')//撞墙
continue ;
if(isupper(maze[w.x][w.y]) && maze[w.x][w.y]!='X') //door
{
for(int i=0;i<4;i++)
{ //找到对应的门,且有该门的钥匙,且在这种状态下的这个位置未走过
if(maze[w.x][w.y]==door[i] && (w.k & (1<<i)) && (!mark[w.x][w.y][w.k]))
{
mark[w.x][w.y][w.k]=true;
q.push(w);
}
}
}
else if(islower(maze[w.x][w.y])) //key
{
for(int i=0;i<4;i++)
{
if(maze[w.x][w.y]==key[i])
{
w.k|=(1<<i); //key记录得到这把钥匙
if(!mark[w.x][w.y][w.k])
{
mark[w.x][w.y][w.k]=true;
q.push(w);
}
}
}
}
else if(!mark[w.x][w.y][w.k]) //普通的路
{
mark[w.x][w.y][w.k]=true;
q.push(w);
}
}
}
printf("The poor student is trapped!\n");
}
int main()
{
while(scanf("%d %d",&n,&m) && (m ||n))
{
node s;
memset(mark,0,sizeof(mark));
for(int i=0;i<n;i++)
{
scanf("%s",maze[i]);
for(int j=0;j<m;j++)
if(maze[i][j]=='*')
s.x=i,s.y=j;
}
s.k=0;
s.t=0;
bfs(s);
}
return 0;
}