题目链接
题意如下:
悟空(K)救唐僧(T),在一个迷宫里,集齐m把钥匙方可救出唐僧(否则就算找到唐僧也只能和他擦肩而过0,0),条件:
1.每次移动花费1个单位时间,遇到蛇(最多5条),杀死它花费一个单位时间。
2.如果你进入了一个房间放着第w把钥匙,只有在你有前w-1把钥匙的情况下你才能得到这把钥匙,否则不能得到。
比如 KT21 ,从K开始走 :右右右左左 花费5个单位时间。
3.输入 0 0表示结束。
首先因为因为钥匙的问题想道bfs+状态压缩(这时想到的是压缩钥匙情况),
后面发现有蛇的存在没法bfs,换dfs+状态压缩(依然压钥匙)果断超时/(ㄒoㄒ)/~~,
再后面才发现蛇只有5条,所以蛇也可以压缩,但是以为是9把钥匙的排列(2^9),
钥匙那一维开了2100爆了,仔细一看题发现只要有第m把钥匙就肯定有前m-1把钥匙,
不可能出现101(即有第一三把 ,没有第二把)的情况。
(和以前做的 钥匙门 的状态压缩不一样O__O "…)
即钥匙数从1~m按序号慢慢叠加(具体请看代码)。
注意本人代码 存蛇的状态是从2^1开始存,
即000010代表第一条蛇被杀,111110表示5条蛇都被杀。
#include <iostream> #include <stdio.h> #include <string.h> #include <queue> #define INF 0xfffffff using namespace std; typedef struct ac { int x,y,t; int k,snak; //钥匙状态,蛇状态 }node; int fmin(int a,int b){return a<b?a:b;} int dirx[]={0,0,1,0,-1},diry[]={0,1,0,-1,0}; int snakx[10],snaky[10],snakl; //记录蛇的位置即序号 int m,n,time; bool mark[105][105][10][64]; //判断在有不同的key的各个位置是否出现过 char maze[105][105]; int which_snak(int x,int y){ //判断该位置是第几条蛇 for(int i=1;i<=snakl;++i) if(x==snakx[i] && y==snaky[i]) return i; } void bfs(node s){ queue <node> q; mark[s.x][s.y][s.k][s.snak]=true; q.push(s); while(!q.empty()){ s=q.front(); q.pop(); // printf("%d %d %d %d\n",s.x,s.y,s.k,s.snak); if(s.t>time)continue; //凑齐m把钥匙就可以去取经了 if(maze[s.x][s.y]=='T' && s.k==m){ time =fmin(time,s.t); continue ; } for(int i=1;i<=4;i++){ node w=s; w.x+=dirx[i]; w.y+=diry[i]; w.t++; //撞墙 if(w.x<1 || w.x>n || w.y<1 || w.y>n || maze[w.x][w.y]=='#') continue; char c=maze[w.x][w.y]; if(c=='S'){ //蛇 int j=which_snak(w.x,w.y); if((w.snak&(1<<j))==0){//该蛇未死, w.snak |= (1<<j); w.t++; //杀掉(花费额外1个单位时间) // printf("!!\n"); } if(!mark[w.x][w.y][w.k][w.snak]){ q.push(w); mark[w.x][w.y][w.k][w.snak]=true; } } else if(isdigit(c)){ //钥匙 //只有手上有前k把钥匙才能捡起第k+1把钥匙 if(w.k+1==c-'0') w.k++; if(!mark[w.x][w.y][w.k][w.snak]){ mark[w.x][w.y][w.k][w.snak]=true; q.push(w); } } else if(!mark[w.x][w.y][w.k][w.snak]){ //普通的路 mark[w.x][w.y][w.k][w.snak]=true; q.push(w); } } } } int main() { while(scanf("%d %d",&n,&m) && (m || n)){ node s; memset(mark,false,sizeof(mark)); snakl=0; for(int i=1;i<=n;i++){ scanf("%s",&maze[i][1]); for(int j=1;j<=n;j++) if(maze[i][j]=='K') s.x=i,s.y=j; else if(maze[i][j]=='S') snakx[++snakl]=i,snaky[snakl]=j; } time=INF; s.k=0; s.snak=0; s.t=0; bfs(s); if(time==INF )printf("impossible\n"); else printf("%d\n",time); } return 0; }