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

【题意】

  1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛, 营救被
敌军俘虏的大兵瑞恩。 瑞恩被关押在一个迷宫里, 迷宫地形复杂, 但幸好麦克得到了迷宫的
地形图。 迷宫的外形是一个长方形, 其南北方向被划分为 N 行,东西方向被划分为 M 列,
于是整个迷宫被划分为 N× M 个单元。每一个单元的位置可用一个有序数对(单元的行号,
单元的列号)来表示。南北或东西方向相邻的 2 个单元之间可能互通, 也可能有一扇锁着的
门,或者是一堵不可逾越的墙。迷宫中有一些单元存放着钥匙, 并且所有的门被分成 P 类,
打开同一类的门的钥匙相同, 不同类门的钥匙不同。
大兵瑞恩被关押在迷宫的东南角,即(N, M)单元里, 并已经昏迷。 迷宫只有一个入口,
在西北角。 也就是说, 麦克可以直接进入(1, 1)单元。 另外,麦克从一个单元移动到另一个
相邻单元的时间为 1, 拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。

´数据输入:
由文件 input.txt 提供输入数据。 第 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)。
输入数据中同一行各相邻整数之间用一个空格分隔。

 

输入文件示例
input.txt
4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1

输出文件示例
output.txt
14

 

 

 

【分析】

  就是分层图最短路,钥匙状压加入状态点中。

  然后路径长度都是1,所以每个点都只会算一次。

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cmath>
 8 #include<map>
 9 using namespace std;
10 #define Maxn 20
11 
12 int a[Maxn][Maxn][6],ky[Maxn][Maxn][20];
13 int bx[6]={0,0,1,-1,0},
14     by[6]={0,1,0,0,-1};
15 int n,m,p,sk;
16 
17 void init()
18 {
19     scanf("%d%d%d",&n,&m,&p);
20     int sm;
21     scanf("%d",&sm);
22     memset(a,0,sizeof(a));
23     for(int i=1;i<=sm;i++)
24     {
25         int x1,y1,x2,y2,g;
26         scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
27         if(g==0) g=-1;
28         for(int k=1;k<=4;k++) if(x1+bx[k]==x2&&y1+by[k]==y2)
29         {
30             a[x1][y1][k]=g;
31             a[x2][y2][5-k]=g;
32             break;
33         }
34     }
35     scanf("%d",&sk);
36     memset(ky,0,sizeof(ky));
37     for(int i=1;i<=sk;i++)
38     {
39         int x,y,q;
40         scanf("%d%d%d",&x,&y,&q);
41         ky[x][y][++ky[x][y][0]]=q;
42     }
43 }
44 
45 struct node
46 {
47     int x,y,s;
48 };
49 
50 int dis[20][20][1010];
51 queue<node > q;
52 void spfa()
53 {
54     while(!q.empty()) q.pop();
55     memset(dis,-1,sizeof(dis));
56     node ft;ft.x=1;ft.y=1;ft.s=0;
57     q.push(ft);dis[1][1][0]=0;
58     int ans=-1;
59     while(!q.empty())
60     {
61         node now=q.front();
62         int x=now.x,y=now.y,s=now.s;
63         for(int i=1;i<=4;i++) if(a[x][y][i]!=-1&&x+bx[i]>=1&&x+bx[i]<=n&&y+by[i]>=1&&y+by[i]<=m)
64         {
65             int nx=x+bx[i],ny=y+by[i],ns=s;
66             if(a[x][y][i]!=0&&((1<<a[x][y][i]-1)&s)==0) continue;
67             // if(ky[nx][ny]) ns|=(1<<ky[nx][ny]-1);
68             for(int l=1;l<=ky[nx][ny][0];l++) ns|=(1<<ky[nx][ny][l]-1);
69             if(dis[nx][ny][ns]==-1)
70             {
71                 dis[nx][ny][ns]=dis[x][y][s]+1;
72                 if(nx==n&&ny==m) {ans=dis[nx][ny][ns];break;}
73                 node tt;
74                 tt.x=nx,tt.y=ny,tt.s=ns;
75                 q.push(tt);
76             }
77         }
78         if(ans!=-1) break;
79         q.pop();
80     }
81     printf("%d\n",ans);
82 }
83 
84 int main()
85 {
86     init();
87     spfa();
88     return 0;
89 }
View Code

 

 

2016-11-06 14:33:08

posted @ 2016-11-06 14:28  konjak魔芋  阅读(422)  评论(0编辑  收藏  举报