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

Posted №〓→龙光←

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流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


分层图最短路属于网络流问题。。。。?!
这题显然不难,分层图最短路裸题,注意细节:一个格子可以放多把钥匙,转移的时候边界不要越界(穿墙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 }

 

 

以上是关于网络流24题----14孤岛营救问题的主要内容,如果未能解决你的问题,请参考以下文章

网络流24题 No.14 孤岛营救问题 (分层图最短路)

[CTSC 1999]拯救大兵瑞恩&[网络流24题]孤岛营救问题

网络流24题

网络流 24 题 解题报告

网络流 24 题 解题报告

网络流24题(好大的坑啊)