首页 > 代码库 > 【网络流24题----14】孤岛营救问题

【网络流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;else141     cout<<ans<<endl;142     return 0;143 }

 

 

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