1. 程式人生 > >洛谷 P4011 孤島營救問題【bfs】

洛谷 P4011 孤島營救問題【bfs】

read cnblogs ret int 單向 線性 etc 註意 ios

註意:

  • 一個點可能有多把鑰匙,所以把每個點有鑰匙的情況狀壓一下
  • 兩個點之間有障礙的情況只給出了單向,存的時候記得存一下反向

b[i][j]表示當前點擁有鑰匙的狀態,g[x1][y1][x2][y2]表示兩點之間門的類型(0表示沒有,-1表示墻比較方便),f[i][j][k]表示點(i,j)在擁有k狀態鑰匙的情況下的最小步數,v[i][j][k]表示f[i][j][k]的狀態是否在bfs隊列裏。然後轉移比較類似spfa

以及終於知道為什麽這種題會在24題裏了…因為24全名“網絡流與線性規劃二十四題”…

#include<iostream>
#include<cstdio>
#include<queue> using namespace std; const int inf=1e9,dx[]={1,-1,0,0},dy[]={0,0,-1,1}; int n,m,p,t,s,g[15][15][15][15],b[15][15],f[15][15][20005]; bool v[15][15][20005]; struct qwe { int x,y,s; }now; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘
) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } int main() { n=read(),m=read(),p=read(),t=read(); for(int i=1;i<=t;i++) { int x1=read(),y1=read(),x2=read(),y2=read(),z=read(); z=z==0
?-1:z; g[x1][y1][x2][y2]=z;g[x2][y2][x1][y1]=z; } s=read(); for(int i=1;i<=s;i++) { int x=read(),y=read(),z=read(); b[x][y]=b[x][y]|(1<<z); } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=0;k<(1<<14);k++) f[i][j][k]=inf; queue<qwe>q; now.x=1,now.y=1,now.s=b[1][1]; f[1][1][now.s]=0; v[1][1][now.s]=1; q.push(now); while(!q.empty()) { int x=q.front().x,y=q.front().y,z=q.front().s; v[x][y][z]=0; q.pop(); for(int i=0;i<4;i++) { int x1=x+dx[i],y1=y+dy[i]; if(x1<1||x1>n||y1<1||y1>m||g[x][y][x1][y1]==-1||(g[x][y][x1][y1]>0&&!((1<<g[x][y][x1][y1])&z))) continue; int w=z|b[x1][y1];//cout<<x1<<" "<<y1<<" "<<w<<" "<<f[x1][y1][w]<<endl; if(f[x1][y1][w]>f[x][y][z]+1) { f[x1][y1][w]=f[x][y][z]+1; if(!v[x1][y1][w]) { now.x=x1,now.y=y1,now.s=w; v[x1][y1][w]=1; q.push(now); } } } } int ans=inf; for(int i=0;i<(1<<14);i++) ans=min(ans,f[n][m][i]); printf("%d\n",ans==inf?-1:ans); return 0; }

洛谷 P4011 孤島營救問題【bfs】