codevs 1911孤岛营救问题/2219拯救大兵瑞恩
来源:互联网 发布:微信运动微信数据来源 编辑:程序博客网 时间:2024/04/28 22:17
题目描述 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拯救大兵瑞恩
- 【CTSC1999】拯救大兵瑞恩(孤岛营救问题)
- [codevs 1911] 孤岛营救问题
- 拯救大兵瑞恩
- [CTSC1999]营救大兵瑞恩
- [CTSC99]拯救大兵瑞恩
- 【CTSC1999】【拯救大兵瑞恩】
- codevs1911 孤岛营救问题
- 【搜索+状态压缩】拯救大兵瑞恩
- hdu 4845 拯救大兵瑞恩(bfs)
- 软件项目管理与《拯救大兵瑞恩》
- 【HDU4845】拯救大兵瑞恩(BFS+状态压缩)
- HDU 4845 拯救大兵瑞恩 基本状态压缩bfs
- HDU 4845 拯救大兵瑞恩(BFS+状态压缩)
- 算法:拯救大兵瑞恩(BFS+状态压缩)
- 孤岛营救问题(最短路)
- 【网络流24题】孤岛营救问题
- 网络流24题14. 孤岛营救问题
- sizeof与strlen详解
- HBase深入分析之RegionServer
- 开发 linux内核的技术路线
- hdu 5502 Candy Game(dp)
- 用两个队列实现一个栈
- codevs 1911孤岛营救问题/2219拯救大兵瑞恩
- 我为什么要使用哈希(Hash)
- java单引号和双引号的区别
- LeetCode Populating Next Right Pointers in Each Node & Populating Next Right Pointers in Each Node I
- Python文件操作读写文件
- redis可视化客户端
- 2015年工作中遇到的问题101-110
- 单链表之反转链表
- 开源 java CMS - FreeCMS2.4 工作流管理