洛谷 P4011 孤島營救問題【bfs】
阿新 • • 發佈:2018-02-10
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】