欢迎转载,另见版权声明↑↑
内容
1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图。迷宫的外形是一个长方形,其南北方向被划分为行,东西方向被划分为列,于是整个迷宫被划分为 个单元。每一个单元的位置可用一个有序数对(单元的行号,单元的列号)来表示。南北或东西方向相邻的个单元之间可能互通,也可能有一扇锁着的门,或者是一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分成类,打开同一类的门的钥匙相同,不同类门的钥匙不同。
大兵瑞恩被关押在迷宫的东南角,即单元里,并已经昏迷。迷宫只有一个入口,在西北角。也就是说,麦克可以直接进入单元。另外,麦克从一个单元移动到另一个相邻单元的时间为,拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。
试设计一个算法,帮助麦克以最快的方式到达瑞恩所在单元,营救大兵瑞恩。
出入
格式
输入
第一行有三个整数,分别表示的值。
第二行是一个整数,表示迷宫中门和墙的总数。
第行,有五个整数,依次为:
- 当时,表示单元与单元之间有一扇第类的门
- 当时,表示单元与单元之间有一堵不可逾越的墙(其中,)。
第行是一个整数,表示迷宫中存放的钥匙总数。
第行(),有三个整数,依次为:表示第把钥匙存放在 ()单元里,并且第把钥匙是用来开启第类门的。(其中)。
输入数据中同一行各相邻整数之间用一个空格分隔。
输出
将麦克营救到大兵瑞恩的最短时间的值输出。如果问题无解,则输出。
样例
输入
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
数据
范围
提示
网络流24题https://blog.csdn.net/weixin_43890363/article/details/131648120?spm=1001.2014.3001.5501
题解
和网络流没有任何关系……
设表示走到且钥匙状态为所需要的最小步数。
其中为一个压缩状态,如果二进制下的第位为一,为拥有第把钥匙,否则没有。
#include<bits/stdc++.h>
#define nm 12
using namespace std;
bool key[nm][nm][nm];
int ans,n,m,X1,Y1,g,edge[nm][nm][nm][nm];
int node[nm][nm][1<<nm];
queue<pair<int,int>>q;
void Go(int x,int y){
if(edge[X1][Y1][x][y]==-1||x>n||y>m||node[x][y][g])return;
if(x&&y&&(g&(1<<edge[X1][Y1][x][y])))
node[x][y][g]=ans,
q.push(make_pair(x*m+y-1,g));
}
int main(){
int p,k,x2,y2;
scanf("%d%d%d%d",&n,&m,&p,&k);
while(k--)
scanf("%d%d%d%d%d",&X1,&Y1,&x2,&y2,&g),
edge[x2][y2][X1][Y1]=edge[X1][Y1][x2][y2]=g?g:-1;
scanf("%d",&k);
while(k--)
scanf("%d%d%d",&X1,&Y1,&g),
key[X1][Y1][g]=true;
q.push(make_pair(m,1));
while(!q.empty()){
g=q.front().second;
if(((X1=q.front().first/m)==n)&((Y1=q.front().first%m+1)==m)){
printf("%d",node[X1][Y1][g]);
return 0;
}
q.pop(),ans=++node[X1][Y1][g];
for(int i=1;i<=p;i++)
if(key[X1][Y1][i])node[X1][Y1][g|=(1<<i)]=ans;
Go(X1-1,Y1),Go(X1+1,Y1),Go(X1,Y1-1),Go(X1,Y1+1);
}
printf("-1");
return 0;
}