网络流二十四题之十四 —— 孤岛营救问题(RESCUE)

孤岛营救问题


【问题描述】

1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。

瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图。

迷宫的外形是一个长方形,其南北方向被划分为 N 行,东西方向被划分为 M 列,于是整个迷宫被划分为 N×M 个单元。

每一个单元的位置可用一个有序数对(单元的行号单元的列号)来表示。南北或东西方向相邻的 2 个单元之间可能互通,也可能有一扇锁着的门,或者是一堵不可逾越的墙。

迷宫中有一些单元存放着钥匙,并且所有的门被分成 P 类,打开同一类的门的钥匙相同,不同类门的钥匙不同。

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

迷宫只有一个入口,在西北角。也就是说,麦克可以直接进入 (11) 单元。

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


【编程任务】

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


【输入描述】

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) 单元之间有一堵不可逾越的墙。
其中, |Xi1Xi2|+|Yi1Yi2|=10<=Gi<=P

K+3 行是一个整数 S ,表示迷宫中存放的钥匙总数。

K+3+J (1<=J<=S) ,有 3 个整数, 依次为 Xi1,Yi1,Qi ,表示第 J 把钥匙存放在 (Xi1,Yi1) 单元里,并且第 J 把钥匙是用来开启第 Qi 类门的(其中 1<=Qi<=P ) 。

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


【输出描述】

输出共一行,即麦克营救到大兵瑞恩的最短时间,如果问题无解,则输出 1


【输入样例】

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
14


【Solution】

这个题目我用的是状压DP。
fx,y,z 表示在 (x,y) ,而状态为 z
然后就可以愉快地DP了。


【Code】

[cpp]
  1. #include   
  2. #include   
  3. #include   
  4.   
  5. #define Min(x,y) ((x)<(y)?(x):(y))  
  6. #define PLA(x,y) (((x)-1)*m+(y))  
  7. #define ff1 data[i][1]  
  8. #define ff2 data[i][2]  
  9.   
  10. using namespace std;  
  11.   
  12. int n,m,p,K,S;  
  13. int minx;  
  14. int cnt;  
  15.   
  16. int head[200],nxt[1000],data[1000][3];  
  17. int f[11][11][20000];  
  18. int map[11][11][11][11];   
  19. bool ms[11][11][210];  
  20. int vis[11][11][20000];  
  21.   
  22. void add(int x,int a,int b){  
  23.     nxt[cnt]=head[x];data[cnt][1]=a;data[cnt][2]=b;head[x]=cnt++;  
  24. }  
  25.   
  26. int judge(int x,int y,int now){  
  27.     for(int i=1;i<=K;i++)  
  28.         if(ms[x][y][i])  
  29.             now|=(1<<(i-1));  
  30.     return now;  
  31. }  
  32.   
  33. void dfs(int x,int y,int now){  
  34.       
  35.     int q[5][4];  
  36.               
  37.     if(vis[x][y][now]!=-1&&vis[x][y][now]==f[x][y][now])return;  
  38.       
  39.     int tmp=judge(x,y,now);  
  40.     vis[x][y][now]=f[x][y][now];  
  41.       
  42.     int cc=0;     
  43.       
  44.     for(int i=head[PLA(x,y)];i!=-1;i=nxt[i]){  
  45.         if((!(map[x][y][ff1][ff2])||(tmp&(1<<(map[x][y][ff1][ff2]-1))))&&(f[ff1][ff2][tmp]==-1||(f[ff1][ff2][tmp]!=-1&&f[ff1][ff2][tmp]>f[x][y][now]+1))){  
  46.             f[ff1][ff2][tmp]=f[x][y][now]+1;  
  47.             q[++cc][1]=ff1;q[cc][2]=ff2;q[cc][3]=tmp;  
  48.         }  
  49.     }  
  50.       
  51.     for(int i=1;i<=cc;i++)dfs(q[i][1],q[i][2],q[i][3]);  
  52.       
  53. }  
  54.   
  55. int main(){  
  56.       
  57.     freopen(”rescue.in”,“r”,stdin);  
  58.     freopen(”rescue.out”,“w”,stdout);  
  59.   
  60.     scanf(”%d%d%d%d”,&n,&m,&p,&K);  
  61.     for(int i=1;i<=K;i++){  
  62.         int x,y,a,b,c;  
  63.         scanf(”%d%d%d%d%d”,&x,&y,&a,&b,&c);  
  64.         if(c==0)c=-1;  
  65.         map[x][y][a][b]=map[a][b][x][y]=c;  
  66.            
  67.     }  
  68.       
  69.     scanf(”%d”,&S);  
  70.     for(int i=1;i<=S;i++){  
  71.         int x,y,z;  
  72.         scanf(”%d%d%d”,&x,&y,&z);  
  73.         ms[x][y][z]=true;   
  74.         ms[x][y][0]=true;  
  75.     }  
  76.       
  77.     minx=0x3f3f3f3f;  
  78.     memset(head,-1,sizeof head);  
  79.     memset(f,-1,sizeof f);  
  80.     memset(vis,-1,sizeof vis);  
  81.       
  82.     for(int i=1;i<=n;i++)  
  83.         for(int j=1;j<=m;j++){  
  84.             if(i+1<=n&&map[i][j][i+1][j]!=-1)add(PLA(i,j),i+1,j);  
  85.             if(j+1<=m&&map[i][j][i][j+1]!=-1)add(PLA(i,j),i,j+1);  
  86.             if(i-1>=1&&map[i][j][i-1][j]!=-1)add(PLA(i,j),i-1,j);  
  87.             if(j-1>=1&&map[i][j][i][j-1]!=-1)add(PLA(i,j),i,j-1);   
  88.         }  
  89.       
  90.     f[1][1][0]=0;  
  91.     dfs(1,1,0);  
  92.       
  93.     for(int i=0;i<=(1<
  94.     if(minx==0x3f3f3f3f)minx=-1;  
  95.     printf(”%d\n”,minx);  
  96.       
  97.     return 0;  
  98. }  

你可能感兴趣的:(题解,网络流,Dp)