最后两题算是这个专题最难的两题了
这题关键是标记数组
我一开始设置的是 四维的 第三维是朝向 第四维是钥匙个数
但是 不同的取法钥匙个数可能会重复 如:取ab钥匙和取ac钥匙都是两枚 导致wa
然后学了状态压缩 用位运算来表示
因为一共十把钥匙 2的十次方才1024 所以开一个1024的数组就行了
int vis[25][25][1025];
当遇到门时 &运算:
if(v.n&(1<<(m1[v.x][v.y]-'A'))) { vis[u.x][u.y][u.n]=1; q.push(v); }
遇到钥匙的时候:|运算
v.n=v.n|(1<<(m1[v.x][v.y]-'a'));
太巧妙了
#include<bits/stdc++.h> using namespace std; char m1[25][25]; int n,m,sx,sy,ex,ey,t; int vis[25][25][5000]; struct node { int x,y,d,n; }; bool inmap(int x,int y) { if(x>=1&&x<=n&&y>=1&&y<=m)return true; return false; } void bfs() { memset(vis,0,sizeof(vis)); int dx[4]={0,1,0,-1}; int dy[4]={1,0,-1,0}; node u; u.x=sx;u.y=sy;u.d=0;u.n=0; queue<node>q; q.push(u); m1[sx][sy]='.'; while(!q.empty()) { u=q.front();q.pop(); // printf("%d %d %d %d ",u.x,u.y,u.d,u.n); if(u.d<=t-1&&m1[u.x][u.y]=='^'){printf("%d ",u.d);return;} for(int i=0;i<4;i++) { node v=u; v.x+=dx[i]; v.y+=dy[i]; v.d=v.d+1; if(inmap(v.x,v.y)&&m1[v.x][v.y]!='*'&&vis[v.x][v.y][v.n]==0&&v.d<t) { if(m1[v.x][v.y]>='a'&&m1[v.x][v.y]<='j') { v.n=v.n|(1<<(m1[v.x][v.y]-'a')); vis[u.x][u.y][u.n]=1; q.push(v); } if(m1[v.x][v.y]>='A'&&m1[v.x][v.y]<='J') { if(v.n&(1<<(m1[v.x][v.y]-'A'))) { vis[u.x][u.y][u.n]=1; q.push(v); } } if((m1[v.x][v.y]=='^'||m1[v.x][v.y]=='.')) {q.push(v);vis[v.x][v.y][v.n]=1;} } } } printf("-1 "); } int main() { while(scanf("%d%d%d",&n,&m,&t)==3) { getchar(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) {scanf("%c",&m1[i][j]); if(m1[i][j]=='@'){sx=i;sy=j;} if(m1[i][j]=='^'){ex=i;ey=j;} } getchar(); } bfs(); getchar(); } return 0; }
回顾:
#include<iostream> #include<queue> #include<cstdio> #include<cstring> using namespace std; #define N 20+5 #define inf 0x3f3f3f3f int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int sx,sy,ex,ey,k; int n,m; char mp[N][N]; bool inmap(int x,int y) { return x>=1&&x<=n&&y>=1&&y<=m; } struct node { int x,y,d,key; }; int vis[N][N][1<<10]; void bfs() { memset(vis,0,sizeof vis); node u,v; u.x=sx; u.y=sy; u.d=0; u.key=0; vis[sx][sy][0]=1; queue<node>q; q.push(u); while(!q.empty()) { u=q.front();q.pop(); // printf("%d %d %d ",u.x,u.y,u.d); if(mp[u.x][u.y]=='^'&&u.d<k){printf("%d ",u.d);return;} for(int i=0;i<4;i++) { node v=u; v.x+=dx[i]; v.y+=dy[i]; v.d+=1; if(v.d>=k)continue; if(islower(mp[v.x][v.y])) v.key=v.key|( 1<<(mp[v.x][v.y]-'a') ); if(isupper(mp[v.x][v.y])) if(( v.key&(1<<(mp[v.x][v.y]-'A')) )==0 )continue; if(inmap(v.x,v.y)&&mp[v.x][v.y]!='*'&&!vis[v.x][v.y][v.key]) { q.push(v); vis[v.x][v.y][v.key]=1; } } } printf("-1 "); } int main() { while(scanf("%d%d%d",&n,&m,&k)==3) { for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='@'){sx=i;sy=j;} bfs(); } return 0; }