网络流24题之孤岛营救问题

这道题其实是一道状态压缩的spfa,把每个状态压缩成一个二进制数。
最后判断答案的时候要注意,因为最快到达的状态不一定是钥匙最多的那个,所以写个循环判断一下

#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
    int x,y,state;
};
int gate[1001][1001];
int vis[101][101][101];
int key[1001][1001];
int f[101][101][1<<10];
int id[1001][1001];
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
const int INF = 0x3f3f3f3f;
int n,m,p;
bool check(int x1,int x2,int y1,int y2,int sta)
{
    int need = gate[id[x1][y1]][id[x2][y2]];
    if(!need) return 0;
    if(need == -1) return 1;
    return (sta >> need) & 1;
}
void bfs()
{
    node a,now;
    a.x = 1;
    a.y  =1;
    a.state = 0;
    queue<node> q;
    q.push(a);
    f[1][1][0] = 0;
    while(!q.empty())
    {
       now = q.front();q.pop();
       vis[now.x][now.y][now.state] = 0;
       int sta = now.state;
       if(key[now.x][now.y]) sta |= key[now.x][now.y];
       for(int i = 0;i<4;i++)
       {
            int x = now.x + dx[i];
            int y = now.y + dy[i];
            if(!x || !y || x > n || y > m) continue;
            if(check(now.x,x,now.y,y,sta))
            {
                if(f[x][y][sta] > f[now.x][now.y][now.state] + 1)
                {
                    f[x][y][sta] = f[now.x][now.y][now.state]+1;
                    if(!vis[x][y][sta])
                    {
                        vis[x][y][sta] = 1;
                        q.push({x,y,sta});
                    }
                }

            }
       }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&p);
    for(int i = 1; i<=n; i++)
    {
        for(int j  =1; j<=m; j++)
        {
            id[i][j] = (i-1)*m + j;
        }
    }
    int k;
    scanf("%d",&k);
    int a,b,c,d,q;
    memset(gate,-1,sizeof(gate));
    memset(f,0x7f,sizeof(f));
    while(k--)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&q);
        gate[id[a][b]][id[c][d]] = q;
        gate[id[c][d]][id[a][b]] = q;
    }
    scanf("%d",&q);
    int sum = 0;
    while(q--)
    {
        scanf("%d%d%d",&a,&b,&c);
        key[a][b] |= (1<<c);
    }
    bfs();
    int ans = INF;
    for(int i = 0;i<(1<<10);i++)
    {
        ans = min(ans,f[n][m][i]);
    }
    if(ans >= INF) ans = -1;
    printf("%d\n",ans);
    return  0;
}

猜你喜欢

转载自blog.csdn.net/lingzidong/article/details/79865491