【网络流24题】孤岛营救问题(分层图+BFS)

8 篇文章 0 订阅
3 篇文章 0 订阅
本文介绍了孤岛营救问题,通过分层图和BFS算法进行解决。作者讨论了如何利用二进制表示枚举钥匙的状态,并构建分层图进行广度优先搜索来求解问题。
摘要由CSDN通过智能技术生成

传送门

    孤岛营救问题

I think

    分层图问题.p枚钥匙是否拿到共有2^p种状态,用二进制表示,对于每一种状态建立分层图广搜求解.
    许久不打BFS生疏了.

Code

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int sm = 11;
const int sn = 1<<15;

int N,M,K,S,mx,Ans;
int a[sm][sm][sm][sm];
int d[sn][sm][sm],vis[sn][sm][sm];
int key[sm][sm];

struct status {
    int x,y,z;
}now;
int xz[4] = {-1,1,0,0};
int yz[4] = {0,0,-1,1};

int Max(int x,int y) { return x>y?x:y; }
int Min(int x,int y) { return x<y?x:y; }

int main() {
    int u,v,x,y,g;
    scanf("%d%d%d",&N,&M,&K);
    scanf("%d",&K);
    for(int i=1;i<=K;++i) {
        scanf("%d%d%d%d%d",&u,&v,&x,&y,&g);
        if(!g) a[x][y][u][v]=a[u][v][x][y]=-1;
        else {
            a[u][v][x][y]|=1<<g;
            a[x][y][u][v]=a[u][v][x][y];
        }
    }
    scanf("%d",&S);
    for(int i=1;i<=S;++i) {
        scanf("%d%d%d",&u,&v,&g);
        key[u][v]|=1<<g;
        mx=Max(mx,g);
    }

    memset(d,0x3f,sizeof(d));
    queue<status>q;
    q.push((status){ 1,1,0 });
    d[0][1][1]=0;

    while(!q.empty()) {
        now = q.front(),q.pop();
        vis[now.z][now.x][now.y]=0;
        for(int i=0;i<4;++i) {
            u=now.x+xz[i];
            v=now.y+yz[i];
            if(u>0&&v>0&&u<=N&&v<=M&&d[now.z][u][v]>d[now.z][now.x][now.y]+1&&a[now.x][now.y][u][v]!=-1&&(now.z&a[now.x][now.y][u][v])==a[now.x][now.y][u][v]) {
                d[now.z|key[u][v]][u][v]=d[now.z][u][v]=d[now.z][now.x][now.y]+1;
                if(!vis[now.z|key[u][v]][u][v]) {
                    vis[now.z|key[u][v]][u][v]=1;
                    q.push((status) { u,v,now.z|key[u][v] });
                } 
            }
        }
    }

    Ans = 0x3f3f3f3f;
    for(int i=0;i<=(1<<mx+1);++i) 
        Ans=Min(Ans,d[i][N][M]);
    if(Ans==0x3f3f3f3f) puts("-1");
    else printf("%d\n",Ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值