概述
题目描述 Description
1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被
敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的
地形图。迷宫的外形是一个长方形,其南北方向被划分为N 行,东西方向被划分为M列,
于是整个迷宫被划分为N×M 个单元。每一个单元的位置可用一个有序数对(单元的行号,
单元的列号)来表示。南北或东西方向相邻的2 个单元之间可能互通,也可能有一扇锁着的
门,或者是一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分成P类,
打开同一类的门的钥匙相同,不同类门的钥匙不同。
大兵瑞恩被关押在迷宫的东南角,即(N,M)单元里,并已经昏迷。迷宫只有一个入口,
在西北角。也就是说,麦克可以直接进入(1,1)单元。另外,麦克从一个单元移动到另一个
相邻单元的时间为1,拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。
«编程任务:
试设计一个算法,帮助麦克以最快的方式到达瑞恩所在单元,营救大兵瑞恩。
输入描述 Input Description
第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 Description
将麦克营救到大兵瑞恩的最短时间的值输出。如果问题无解,则输出-1。
样例输入 Sample Input
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
样例输出 Sample Output
14
其实这道题先前做kac的迷宫的时候接触过,但这道题稍难一些
题目大意是要在地图上有一些单元之间两两有墙,如果有相应的钥匙就可以开门(墙),但有些墙是开不了的,即使有钥匙也不行QAQ
这样的话就可以使用bfs来解决这道题
在搜索过程中保存坐标和已拥有的钥匙数
类似分层的思想,拥有不同的钥匙进行不同的bfs操作
如果可以到达终点的话即是最终答案
保存钥匙时可以使用压位操作,这样只需要3维数组就可以维护状态(某神犇开12维数组用血淋淋的教训告诉我们还是压位好用)
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int map[50][50];
int door[50][50][50][50];
bool use[50][50][50];
int x_x[5]={0,0,0,1,-1};
int y_y[5]={0,1,-1,0,0};
struct doubi{
int x,y,k;
int g;
};
int n,m,p,k;
queue<doubi> q;
bool can(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m){
return true;
}
return false;
}
bool havekey(int k,int num)
{
return k&(1<<num);
}
void addkey(int &k,int num)
{
k|=num;
return ;
}
bool flag=0;
void bfs()
{
doubi fuckcy;
fuckcy.x=1,fuckcy.y=1;
fuckcy.k=0,fuckcy.g=0;
use[1][1][0]=1;
q.push(fuckcy);
while(!q.empty()){
doubi facy=q.front();
q.pop();
int x=facy.x,y=facy.y;
if(x==n&&y==m){
cout<<facy.g<<endl;
flag=1;
return;
}
for(int i=1;i<=4;i++){
int X=x+x_x[i];
int Y=y+y_y[i];
doubi nxt=facy;
nxt.x=X,nxt.y=Y;
if(can(X,Y)&&!use[X][Y][facy.k]){
if(door[x][y][X][Y]==214748364) continue;
if(door[x][y][X][Y]){
if(havekey(nxt.k,door[x][y][X][Y])){
nxt.g=facy.g+1;
if(map[X][Y])
addkey(nxt.k,map[X][Y]);
use[X][Y][nxt.k]=1;
q.push(nxt);
}
else continue;
}
else{
nxt.g=facy.g+1;
if(map[X][Y])
addkey(nxt.k,map[X][Y]);
use[X][Y][nxt.k]=1;
q.push(nxt);
}
}
}
}
}
int main()
{
cin>>n>>m>>p;
cin>>k;
for(int i=1;i<=k;i++){
int x1,y1,x2,y2,v;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&v);
if(v==0){
v=214748364;
}
door[x1][y1][x2][y2]=v;
door[x2][y2][x1][y1]=v;
}
int s;
cin>>s;
for(int i=1;i<=s;i++){
int x,y,q;
scanf("%d%d%d",&x,&y,&q);
map[x][y]|=1<<q;
}
bfs();
if(!flag){
cout<<"-1"<<endl;
}
return 0;
}
顺带一提codevs拯救大兵瑞恩其中一个点的数据是错的
要想过的话还是打个表比较好= =
最后
以上就是含糊日记本为你收集整理的codevs 1911孤岛营救问题/2219拯救大兵瑞恩的全部内容,希望文章能够帮你解决codevs 1911孤岛营救问题/2219拯救大兵瑞恩所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复