题意:
wanghang现在玩一个游戏,他一个迷宫中。他的起点在S,他想到达E点的出口,出口的位置有守卫,他必须在迷宫中收集至少K个金币,才能买通守卫,放他出去。守卫是十分暴躁的,如果他到达出口的位置时身上的金币不足K个的话,守卫就会把wanghang杀掉,这样就GAME OVER了。这个迷宫中还有多个传送门,每次使用传送门需要花费1金币,可以传送到任意一个传送门的位置。
wanghang想尽快通关这个游戏,现在问最少需要多少步可以走出迷宫?
如图:
#######
#E...P#
#...SP#
#.CCC.#
#######
地图中,
#代表墙壁,
.代表空地,
P代表传送门,(传送门个数<=5)
C代表金币,金币不能重复拾取(金币个数<=5)
S,E代表起点,出口(保证只会仅出现一个S和E)
每次可以朝上下左右四个方向移动,使用传送门也算1步。
思路:
显然是一个状态压缩和然后在结合一下记忆化搜索
用一个四维数组vis[][][][]第一维表示x第二维表示y,第三位表示当前所吃的金币的状态(5位二进制对应10进制),第三维表示当前的拥有的金币。
bfs里有5个 元素,x,y,g(上面的二进制状态),v(上面拥有的财富),st当前步骤数
代码:
#include
using namespace std;
#define maxn 311111
#define mod 1000000007
typedef long long LL;
char cmp[15][15]; //字符地图
bool vis[15][15][40][10]; //状态标记
int mp[15][15]; //数字地图
bool mvis[15][15]; //没用到
int godx[10],gody[10]; //金币位置
int px[10],py[10]; //传送门位置
int stepx[5]={0,1,0,-1,0}; //步骤
int stepy[5]={0,0,1,0,-1};
int n,m,k;
int head,wei;
struct NODE {
int x,y,g,v,st; //横纵坐标,金币状态值(五位二进制)。所拥有价值,步骤数
}bfs[111111];
int pan(int x,int y) { //判断这个点是不是在地图内
if(x>=1&&y>=1&&x<=n&&y<=m) return 1;
return 0;
}
void bb(int x,int y,int g,int v,int st,int nn) { //自定义bfs数组添加方法
bfs[nn].x=x;
bfs[nn].y=y;
bfs[nn].g=g;
bfs[nn].v=v;
bfs[nn].st=st;
}
int main () {
//freopen("1.txt","r",stdin);
int t;
int fa;
int god,p;
int sx,sy,ex,ey; //起始点,终点
scanf("%d",&t);
while(t--) {
fa=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i0&&!vis[px[j]][py[j]][gg][vv-1]) {
bb(px[j],py[j],gg,vv-1,st,wei);
wei++;
vis[px[j]][py[j]][gg][vv-1]=1;
}
}
}
// head++;
// continue;
}
for(int i=1;i<=4;i++) { //正常的朝四个方向前进
int xx=bfs[head].x+stepx[i];
int yy=bfs[head].y+stepy[i];
int gg=bfs[head].g;
int vv=bfs[head].v;
int st=bfs[head].st+1;
int lox=0;
if(!pan(xx,yy)) {
continue;
}
if(mp[xx][yy]==1) {
continue;
}
if(xx==ex&&yy==ey) {
if(vv>=k) {
printf("%d\n",st);
fa=1;
break;
}
else {
continue;
}
}
if(mp[xx][yy]==2) {
for(int j=1;j<=god;j++) {
if(xx==godx[j]&&yy==gody[j]) {
lox=j;
break;
}
}
if(!(gg&(1<<(lox-1)))) {
if(!vis[xx][yy][gg|(1<<(lox-1))][vv+1]) {
bb(xx,yy,gg|(1<<(lox-1)),vv+1,st,wei);
wei++;
vis[xx][yy][gg|(1<<(lox-1))][vv+1]=1;
}
}
else {
if(!vis[xx][yy][gg][vv]) {
bb(xx,yy,gg,vv,st,wei);
wei++;
vis[xx][yy][gg][vv]=1;
}
}
continue;
}
if(mp[xx][yy]==3) {
vis[xx][yy][gg][vv]=1;
if(vv==0) continue;
bb(xx,yy,gg,vv,st,wei);
wei++;
/* for(int j=1;j<=p;j++)
if(xx==px[j]&&yy==py[j]) {
lox=j;
break;
}
for(int j=1;j<=p;j++) {
if(j!=lox) {
if(!vis[godx[j]][gody[j]][gg][vv-1]) {
bb(godx[j],gody[j],gg,vv-1,st,wei);
wei++;
vis[godx[j]][gody[j]][gg][vv-1]=1;
}
}
}*/
continue;
}
if(vis[xx][yy][gg][vv]==0) {
bb(xx,yy,gg,vv,st,wei);
wei++;
vis[xx][yy][gg][vv]=1;
}
}
head++;
}
// for(int i=1;i<=wei-1;i++) {
// cout<