给出一个N*N的矩阵,开启牢门需要收集齐m种钥匙,且必须收集了前i-1种钥匙才能收集第i种钥匙,最终收集齐了回到关押唐僧的房间拯救唐僧,经过一个‘S‘的房间时需要额外耗时把蛇打死,蛇最多5条,所以状压一下用优先队列BFS求最小时间即可。
#include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <vector> #include <cstring> #include <algorithm> #define inf 1<<29 using namespace std; const int maxn=111; char str[maxn][maxn]; int n,m; int ans; int map[maxn][maxn]; int dp[maxn][maxn][11];//访问到坐标(x,y)身上有i个钥匙的步数 int dir[4][2]= {0,1,0,-1,1,0,-1,0}; struct node { int x,y; int step; int snake; int k; friend bool operator<(node a,node b) { return a.step>b.step; } }; int go(int x,int y) { if(x>=0&&x<n&&y>=0&&y<n&&str[x][y]!='#') { return 1; } return 0; } void solve(int x,int y) { priority_queue<node> q; node front,now; now.x=x; now.y=y; now.step=0; now.snake=0; now.k=0; q.push(now); while(!q.empty()) { front=q.top(); q.pop(); x=front.x; y=front.y; if(str[x][y]=='T'&&front.k==m) { ans=min(ans,front.step); } for(int i=0;i<4;i++) { int fx=x+dir[i][0]; int fy=y+dir[i][1]; now.x=fx; now.y=fy; now.step=front.step+1; now.snake=front.snake; now.k=front.k; if(go(fx,fy)) { if(str[fx][fy]=='S') { int k=map[fx][fy]; if(((1<<k)&now.snake)==0) { now.step++; now.snake|=(1<<k); } } if(str[fx][fy]-'0'==now.k+1) { now.k+=1; } if(dp[fx][fy][now.k]>now.step&&now.step<ans) { dp[fx][fy][now.k]=now.step; q.push(now); } } } } } int main() { int cnt; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) { break; } cnt=0; for(int i=0;i<n;i++) { scanf("%s",str[i]); } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(str[i][j]=='S') { map[i][j]=cnt++; } for(int k=0;k<11;k++) { dp[i][j][k]=inf; } } } ans=inf; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(str[i][j]=='K') { solve(i,j); break; } } } if(ans==inf) { printf("impossible\n"); } else { printf("%d\n",ans); } } return 0; }
时间: 2024-12-28 01:29:09