P4011 孤岛营救问题

题目描述

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

大兵瑞恩被关押在迷宫的东南角,即 \((N,M)\) 单元里,并已经昏迷。迷宫只有一个入口,在西北角。也就是说,麦克可以直接进入 \((1,1)\) 单元。另外,麦克从一个单元移动到另一个相邻单元的时间为 \(1\),拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。

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

输入格式
\(1\) 行有 \(3\) 个整数,分别表示 \(N,M,P\) 的值。

\(2\) 行是 \(1\) 个整数 \(K\),表示迷宫中门和墙的总数。

\(i+2\)\((1≤i≤K)\),有 \(5\) 个整数,依次为$X_{i1},Y_{i1},X_{i2},Y_{i2},G_i $

\(G_i≥1\) 时,表示 \((X_{i1},Y_{i1})\) 单元与 \((X_{i2},Y_{i2})\) 单元之间有一扇第 \(G_i\) 类的门

\(G_i=0\) 时,表示 \((X_{i1},Y_{i1})\) 单元与 \((X_{i2},Y_{i2})\) 单元之间有一堵不可逾越的墙
(其中,\(|X_{i1}-X_{i2}|+|Y_{i1}-Y_{i2}|=1,0≤G_i≤P\))。

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

\(K+3+j\) 行(1≤j≤S),有 \(3\) 个整数,依次为 X_{i1},Y_{i1},Q_i :表示第 JJ 把钥匙存放在 (X_{i1},Y_{i1})单元里,并且第 J 把钥匙是用来开启第 \(Q_i\) 类门的。(其中\(1 ≤ Q i ≤ P\))。

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

输出格式
将麦克营救到大兵瑞恩的最短时间的值输出。如果问题无解,则输出 \(-1\)

思路:

首先看样例:

vis[x][y][S] 表示在x y这个位置持有钥匙状态为S是否来过

用结构体队列存4个状态分别是 \(x,y,step\)(步数)\(state\)(钥匙状态)

dor[x1][y1][x2][y2]表示两个点直接是否有墙或者是门。

key[x][y][i]表示x y这个点放的钥匙的种类,(i表示第i个钥匙,同一点有多个钥匙)

num[x][y]表示当前点钥匙数目

坑点:

1.钥匙不是用了就没了((#`O′)喂,没了才有问题吧

2.一个点可以放多个钥匙(人家又没说只放一个。

3.初始点可以放钥匙(特判一下就好了)

上代码!

#include <bits/stdc++.h>
using namespace std;
int n,m,p;
int k;
int dor[15][15][15][15];
bool vis[15][15][2005];
int f[15][15];
int key[15][15][25];
int num[15][15];
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};

struct node{
	int x,y,step,st;
};
queue<node> q;



inline int bfs(){
	int nows=0;
	for (int i=1;i<=num[1][1];i++){
		nows|=(1<<(key[1][1][i]-1));
	}vis[1][1][nows]=1;
	q.push((node{1,1,0,nows}));
	while (!q.empty()){
		node now=q.front();q.pop();
		if (now.x==n&&now.y==m)return now.step;
		for (int i=1;i<=4;i++){
			int xx=now.x+dx[i],yy=now.y+dy[i],t;
			if(xx<1||yy<1||xx>n||yy>m) continue;
			if(dor[now.x][now.y][xx][yy]==-1) continue;
			if((t=dor[now.x][now.y][xx][yy])!=0)
			if((now.st&(1<<(t-1)))==0) continue;
			int cost=now.st;
			for(int j=1;j<=num[xx][yy];j++)
				cost|=(1<<(key[xx][yy][j]-1));
			if(vis[xx][yy][cost]) continue;
			vis[xx][yy][cost]=1;
			q.push((node){xx,yy,now.step+1,cost});
		}
	}
	return -1;
}

int main(){
	scanf("%d%d%d",&n,&m,&p);
	scanf("%d",&k);
	int x1,y1,x2,y2,g,q,s;
	for (int i=1;i<=k;i++){
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
		if (g==0){
			dor[x1][y1][x2][y2]=-1;
			dor[x2][y2][x1][y1]=-1;
		}
		else{
			dor[x1][y1][x2][y2]=g;
			dor[x2][y2][x1][y1]=g;
		}
	}
	scanf("%d",&s);
	for (int i=1;i<=s;i++){
		scanf("%d%d%d",&x1,&y1,&q);
		key[x1][y1][++num[x1][y1]]=q;
	}
	printf("%d",bfs());
	return 0;
}
posted @ 2021-08-24 07:37  hewt  阅读(15)  评论(0编辑  收藏  举报