【网络流24题----14】孤岛营救问题

孤岛营救问题

Time Limit: 1 Sec  Memory Limit: 128 MB

Description

1944年,特种兵麦克接到国防部的命令。要求马上赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图。迷宫的外形是一个长方形,其南北方向被划分为 N行,东西方向被划分为 M列,于是整个迷宫被划分为 N×M个单元。每个单元的位置可用一个有序数对 (单元的行号,单元的列号)来表示。南北或东西方向相邻的 2个单元之间可能互通,也可能有一扇锁着的门。或者是一堵不可逾越的墙。

迷宫中有一些单元存放着钥匙,而且全部的门被分成 P类。打开同一类的门的钥匙同样,不同类门的钥匙不同。

大兵瑞恩被关押在迷宫的东南角。即(N,M)单元里,并已经昏迷。

迷宫仅仅有一个入口,在西北角。

也就是说,麦克能够直接进入(1,1)单元。

另外,麦克从一个单元移动到还有一个相邻单元的时间为 1。拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。

试设计一个算法,帮助麦克以最快的方式到达瑞恩所在单元。营救大兵瑞恩。

Input

第 1行有 3个整数。分别表示 N,M,P的值。

第 2行是 1个整数 K,表示迷宫中门和墙的总数。
第 I+2行(1<=I<=K),有 5个整数。依次为 Xi1,Yi1,Xi2,Yi2,Gi:
  当 Gi>=1时。表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一扇第 Gi类的门。
  当 Gi=0时,表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一堵不可逾越的墙(当中,|Xi1-Xi2|+|Yi1-Yi2|=1, 0<=Gi<=P)。
第 K+3行是一个整数 S,表示迷宫中存放的钥匙总数。
第 K+3+J行(1<=J<=S)。有 3个整数,依次为 Xi1,Yi1,Qi:表示第 J把钥匙存放在(Xi1,Yi1)单元里,而且第 J把钥匙是用来开启第 Qi类门的。(当中 1<=Qi<=P)。

输入数据中同一行各相邻整数之间用一个空格分隔。

Output

输出麦克营救到大兵瑞恩的最短时间的值。假设问题无解,则输出-1。

Sample Input

4 4 991 2 1 3 21 2 2 2 02 1 2 2 02 1 3 1 02 3 3 3 02 4 3 4 13 2 3 3 03 3 4 3 04 3 4 4 022 1 24 2 1

Sample Output

14

HINT

N,M,P <= 10

K < 150

Source

网络流24题


分层图最短路属于网络流问题。。。。?!

这题显然不难,分层图最短路裸题,注意细节:一个格子可以放多把钥匙,转移的时候边界不要越界(穿墙play)


  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 using namespace std;
  9 #define maxn 110
 10 #define ZT ((1<<12)+1)
 11 #define llg long long
 12 #define maxlen 100000
 13 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 14 #define inf (llg)1e16
 15 llg n,m,to[5][2],dis[maxn][ZT],yaoshi[maxn],bj[maxn][ZT];
 16 llg p,k,S,head,tail;
 17
 18 llg num_(llg x,llg y){return (x-1)*m+y;}
 19
 20 struct node
 21 {
 22     llg p1,p2,ty;
 23 }e[151];
 24
 25 struct data
 26 {
 27     llg po,set;
 28 }dl[maxlen+5];
 29
 30 vector<llg>a[maxn];
 31
 32 void init()
 33 {
 34     to[1][1]=1,to[2][1]=-1,to[3][0]=1,to[4][0]=-1;
 35     cin>>n>>m>>p>>k;
 36     p++;
 37     llg x1,y1,x2,y2,z;
 38     for (llg i=1;i<=k;i++)
 39     {
 40         scanf("%lld%lld%lld%lld%lld",&x1,&y1,&x2,&y2,&z);
 41         llg x=num_(x1,y1); llg y=num_(x2,y2);
 42         if (x>y) swap(x,y);
 43         e[i].p1=x,e[i].p2=y,e[i].ty=z;
 44     }
 45     for (llg i=1;i<=n;i++)
 46         for (llg j=1;j<=m;j++)
 47         {
 48             for (llg w=1;w<=4;w++)
 49                 if (i+to[w][0]>=1 && i+to[w][0]<=n && j+to[w][1]>=1 && j+to[w][1]<=m)
 50                     a[num_(i,j)].push_back(num_(i+to[w][0],j+to[w][1]));
 51         }
 52     cin>>S;
 53     for (llg i=1;i<=S;i++)
 54     {
 55         scanf("%lld%lld%lld",&x1,&y1,&z);
 56         yaoshi[num_(x1,y1)]|=(1<<z);
 57     }
 58     n*=m;
 59     for (llg i=1;i<=n;i++)
 60         for (llg j=0;j<(1<<p);j++) dis[i][j]=inf;
 61     head=0,tail=1,dl[1].po=1,dl[1].set=0;
 62     dis[1][0]=0;
 63 }
 64
 65 llg find(llg x,llg y)
 66 {
 67     for (llg i=1;i<=k;i++)
 68         if ((e[i].p1==x && e[i].p2==y) || (e[i].p1==y && e[i].p2==x)) return e[i].ty;
 69     return -1;
 70 }
 71
 72 void spfa()
 73 {
 74     llg x,v,se,w;
 75     do
 76     {
 77         head%=maxlen; head++;
 78         x=dl[head].po,se=dl[head].set,w=a[x].size();
 79         bj[x][se]=0;
 80         for (llg i=0;i<w;i++)
 81         {
 82             v=a[x][i];
 83             llg color=find(x,v);
 84             //if (color==0) continue;
 85             if (yaoshi[x]!=0)
 86             {
 87                 llg nse=se|yaoshi[x];
 88                 if (dis[x][nse]>dis[x][se])
 89                 {
 90                     dis[x][nse]=dis[x][se];
 91                     if (!bj[x][nse])
 92                     {
 93                         bj[x][nse]=1;
 94                         tail%=maxlen;
 95                         dl[++tail].po=x,dl[tail].set=nse;
 96                     }
 97                 }
 98             }
 99
100             if (color==0) continue;
101             if (color>0)
102             {
103                 if ((se&(1<<color))==0) continue;
104             }
105             if (dis[v][se]>dis[x][se]+1)
106             {
107                 dis[v][se]=dis[x][se]+1;
108                 if (!bj[v][se])
109                 {
110                     bj[v][se]=1;
111                     tail%=maxlen;
112                     dl[++tail].po=v,dl[tail].set=se;
113                 }
114             }
115             if (yaoshi[x]!=0)
116             {
117                 llg nse=se|yaoshi[x];
118                 if (dis[v][nse]>dis[x][se]+1)
119                 {
120                     dis[v][nse]=dis[x][se]+1;
121                     if (!bj[v][nse])
122                     {
123                         bj[v][nse]=1;
124                         tail%=maxlen;
125                         dl[++tail].po=v,dl[tail].set=nse;
126                     }
127                 }
128             }
129         }
130     }while (head!=tail);
131 }
132
133 int main()
134 {
135     yyj("save");
136     init();
137     spfa();
138     llg ans=inf;
139     for (llg i=0;i<(1<<p);i++) ans=min(ans,dis[n][i]);
140     if (ans==inf) cout<<-1;else
141     cout<<ans<<endl;
142     return 0;
143 }
时间: 2024-10-14 22:48:11

【网络流24题----14】孤岛营救问题的相关文章

【线性规划与网络流24题】孤岛营救问题 分层图

孤岛营救问题 Time Limit: 1 Sec  Memory Limit: 128 MB Description 1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图.迷宫的外形是一个长方形,其南北方向被划分为 N行,东西方向被划分为 M列,于是整个迷宫被划分为 N×M个单元.每一个单元的位置可用一个有序数对 (单元的行号,单元的列号)来表示.南北或东西方向相邻的 2个单元之间可能

14. [网络流24题] 搭配飞行员

14. [网络流24题] 搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述] 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 如图,假设有10个驾驶员,如图中的V1,V2,…,V10就代表达10个驾驶员,其中V1,V2

COGS 14. [网络流24题] 搭配飞行员

14. [网络流24题] 搭配飞行员 建边的时候要先从源点向主飞行员和从副飞行员向汇点连边 输入的时候只在两人之间连边 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 #define maxn 10000 5 #define inf 100000000 6 int n,m,src,dec,cur[maxn],ans,lev[maxn]; 7 int front[maxn],head,tail,que

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

网络流24题小结

网络流24题 前言 网络流的实战应用篇太难做了,因此先完善这一部分 ## 第一题:飞行员配对方案 \(BSOJ2542\)--二分图 最优匹配 题意 两国飞行员\(x\)集合\(y\)集合,\(x\)飞行员可以配对特定的\(y\)集合的飞行员(可无),求一对一配对最大数 Solution 二分图最大匹配裸题,最大流实现 建图:(设\(i\in x\)而\(i'\in y\)) \((S,i,1)~(i',T,1)\) 对\((i,j')\)可匹配\((i,j',1)\) Code 略 ## 第二

【网络流24题】魔术球问题

P1226 - [网络流24题]魔术球问题 Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可 放11个球. ′编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. Input 第1 行有 1个正整数n,表示柱子数. Output 第一行是球

【网络流24题】 No.12 软件补丁问题(最小转移代价 最短路)

[题意] T 公司发现其研制的一个软件中有 n 个错误, 随即为该软件发放了一批共 m 个补丁程序. 每一个补丁程序都有其特定的适用环境, 某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以使用.一个补丁在排除某些错误的同时, 往往会加入另一些错误.换句话说, 对于每一个补丁 i, 都有 2 个与之相应的错误集合 B1[i]和 B2[i],使得仅当软件包含 B1[i]中的所有错误, 而不包含 B2[i]中的任何错误时, 才可以使用补丁 i. 补丁 i 将修复软件中的某些错误 F1[

BZOJ_1221_ [HNOI2001]_软件开发(网络流24题,最小费用流)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1221 n天,每天需要r个毛巾,用完以后可以洗,要么花fa洗a天,要么花fb洗b天,毛巾不够了可以话f买一个,问最少需要多少钱. 分析 把每天拆成两个点:x[i]表示第i天的脏毛巾,y[i]表示第i天要用的毛巾. 1.s向x[i]连弧,容量为r[i],花费为0,表示每天会用脏r[i]条毛巾. 2.x[i]向x[i+1]连弧(注意边界),容量为INF,花费为0,表示把第i天的脏毛巾搁置到第i+1

[网络流24题]魔术球问题

问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11个球. ´编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. ´数据输入: 文件第1 行有 1个正整数n,表示柱子数. ´结果输出: 文件的第一行是球数. 数据规模 n<=60  保证答案小于16