HDU 5094 题解(状压BFS)
题面:
题目中文大意:
这个故事发生在“星际迷航”的背景下。
“星际争霸”的副队长史波克落入克林贡的诡计中,被关押在他们的母亲星球Qo’noS上。
企业的上尉詹姆斯·T·柯克(James T. Kirk)不得不乘宇宙飞船去救他的副手。幸运的是,他偷走了史波克所在的迷宫地图。
迷宫是一个矩形,它有n行垂直和m列水平,换句话说,它被分为n * m个位置。有序对(行号,列号)表示迷宫中的位置。柯克从当前位置移动到下一个花费1秒。而且他只有在以下情况下才能移动到下一个位置:
下一个位置与当前柯克的位置相邻(上下或左右)(4个方向)
开着的门是可以通行的,但锁着的门不是。
柯克不能通过一堵墙
有几种门是默认锁定的。钥匙只能打开相同类型的门。柯克必须在打开相应的门之前拿到钥匙,这样很浪费时间。
柯克的初始位置是(1,1),而史波克位于(n,m)的位置。你的任务是帮助Kirk尽快找到史波克。
Input
输入包含很多测试样例。
每个测试样例由几行组成。第一行中有三个整数,分别代表n,m和p (1<= n, m <=50, 0<= p <=10).
第二行只列出一个整数k,表示门和墙的总数(0<= k <=500).
在下面的k行中有5个整数,表示 i1, y i1, x i2, y i2, g i; 当g i >=1,表示在位置 (x i1, y i1) 和 (x i2, y i2)之间存在类型gi的门;当g i = 0,说明 (x i1, y i1)和 (x i2, y i2),之间存在一堵墙 ( | x i1 - x i2 | + | y i1 - y i2 |=1, 0<= g i <=p )
下面的行是一个整数S,表示迷宫中的钥匙的总数。(0<= S <=50).
在下面的S行中有三个整数,分别表示x i1, y i1和q i这意味着类型为qi的钥匙位于位置 i (x i1, y i1), (1<= q i<=p).
Output
输出Kirk可能达到史波克的可能最小的秒数。
如果没有可能的计划,输出-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
分析:
此题应使用广度优先搜索(BFS)
状态压缩:有10种钥匙,那么我们用10位二进制来存储钥匙串(即一个int整型变量),第i-1位是1表示有第i种钥匙,为0则没有钥匙
用位运算来判断是否能通过门(这些操作很常用,应牢记)
将第i种钥匙加入钥匙串key
代码:key|=(1<<(i-1))
例:key=0010 ,i=4,1<<(i-1)=1000,0010|1000=1010拿着钥匙串key,是否能通过第i种门
代码:if(key&(1<<(i-1)==0) continue
例:(没拿到第5种钥匙,想通过第5种门)key=01101,i=5,1<<(i-1)=10000,00101|10000=0,通不过,continue
(拿到第4种钥匙,想通过第4种门)key=01101,i=4,1<<(i-1)=01000,00101|10000=01000,可通过
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 56
#define maxqu 50*50*(1<<11)+10
using namespace std;
int n,m,p,k,s;
struct node{
int x;
int y;
int step;
int key;//存储钥匙
};
node now,nex;
node queue[maxqu];
int door[maxn][maxn][maxn][maxn];//邻接矩阵存门
int keys[maxn][maxn];//二维数组存储每一个点的钥匙
int used[maxn][maxn][2055];//标志是否走过
const int walkx[4]={1,-1,0,0},walky[4]={0,0,1,-1};
int fread(){//快速输入
int x=0;
char c=getchar();
int sign=1;
while(c<'0'||c>'9') {
if(c=='-') sign=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*sign;
}
bool judge(int x1,int y1,int x2,int y2){
if(door[now.x][now.y][nex.x][nex.y]==0) return false;//有墙
if(x2>=1&&x2<=n&&y2>=1&&y2<=m) return true;
else return false;
}
int bfs(){
int head=0,tail=0;
int tmp;
queue[0].x=1;
queue[0].y=1;
queue[0].step=0;
queue[0].key|=keys[1][1];//起点有钥匙的特判
memset(used,0,sizeof(used));
used[1][1][queue[0].key]=1;
do{
now=queue[head];
if(now.x==n&&now.y==m) return now.step;
for(int i=0;i<4;i++){
nex.x=now.x+walkx[i];
nex.y=now.y+walky[i];
nex.key=now.key;
nex.step=now.step;
if(judge(now.x,now.y,nex.x,nex.y)){
if(door[now.x][now.y][nex.x][nex.y]>0){//开门
tmp=door[now.x][now.y][nex.x][nex.y]-1;
if((nex.key&(1<<tmp))==0) continue;
}
if(keys[nex.x][nex.y]>0){//拿钥匙
nex.key|=keys[nex.x][nex.y];
}
if(used[nex.x][nex.y][nex.key]==1) continue;
used[nex.x][nex.y][nex.key]=1;
tail++;
queue[tail].x=nex.x;
queue[tail].y=nex.y;
queue[tail].key=nex.key;
queue[tail].step=nex.step+1;
}
}
head++;
}while(head<=tail);
return -1;
}
int main(){
// freopen("data.txt","r",stdin);
int x1,y1,x2,y2,v;
while(cin>>n>>m>>p){
memset(door,-1,sizeof(door));
memset(keys,0,sizeof(keys));
k=fread();
for(int i=1;i<=k;i++){
x1=fread();
y1=fread();
x2=fread();
y2=fread();
v=fread();
door[x1][y1][x2][y2]=v;//>0门,=0墙,-1无
door[x2][y2][x1][y1]=v;
}
cin>>s;
for(int i=1;i<=s;i++){
x1=fread();
y1=fread();
v=fread();
keys[x1][y1]|=(1<<(v-1));//预处理钥匙,注意一个位置有多个钥匙的情况
}
cout<<bfs()<<endl;
}
}
HDU 5094 题解(状压BFS)的更多相关文章
- 拯救大兵瑞恩 HDU - 4845(状压bfs || 分层最短路)
1.状压bfs 这个状压体现在key上 我i们用把key状压一下 就能记录到一个点时 已经拥有的key的种类 ban[x1][y1][x2][y1]记录两个点之间的状态 是门 还是墙 还是啥都没有 ...
- HDU 4012 Paint on a Wall(状压+bfs)
Paint on a Wall Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) ...
- HDU Stealing Harry Potter's Precious(状压BFS)
状压BFS 注意在用二维字符数组时,要把空格.换行处理好. #include<stdio.h> #include<algorithm> #include<string.h ...
- POJ 1324 Holedox Moving (状压BFS)
POJ 1324 Holedox Moving (状压BFS) Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 18091 Acc ...
- P2622 关灯问题II(状压bfs)
P2622 关灯问题II 题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯——按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j] ...
- 状压BFS
题意:1个机器人找几个垃圾,求出最短路径. 状压BFS,这道题不能用普通BFS二维vis标记数组去标记走过的路径,因为这题是可以往回走的,而且你也不能只记录垃圾的数量就可以了,因为它有可能重复走同一 ...
- hdu 5094 状压bfs+深坑
http://acm.hdu.edu.cn/showproblem.php?pid=5094 给出n*m矩阵 给出k个障碍,两坐标之间存在墙或门,门最多10种,状压可搞 给出s个钥匙位置及编号,相应的 ...
- HDU 4284Travel(状压DP)
HDU 4284 Travel 有N个城市,M条边和H个这个人(PP)必须要去的城市,在每个城市里他都必须要“打工”,打工需要花费Di,可以挣到Ci,每条边有一个花费,现在求PP可不可以从起点1 ...
- [HNOI2006]最短母串问题——AC自动机+状压+bfs环形处理
Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 32MB Input 第一行是一个正整数n(n< ...
- 洛谷P4011 孤岛营救问题(状压+BFS)
传送门 和网络流有半毛钱关系么…… 可以发现$n,m,p$都特别小,那么考虑状压,每一个状态表示位置以及钥匙的拥有情况,然后每次因为只能走一步,所以可以用bfs求出最优解 然后是某大佬说的注意点:每个 ...
随机推荐
- 1.Linux命令行快捷键、Vim
1. 命令终端的快捷键使用 ctrl+b 左移光标 ctrl+f 右移光标 ctrl+u 删除光标左边的内容 ctrl+k 删除光标右边的内容 ctrl+w 删除光标前的一个单词 =esc+ctrl+ ...
- python学习相关软件安装
爬虫初学者必装的软件!! 一.安装python step1:安装包下载 1.1.官网下载地址:https://www.python.org/ 根据自己电脑系统选择,我选择windowns 有不同版本可 ...
- 部署至Oracle数据库的注意事项
部署至Oracle数据库的注意事项 安装数据库之前1)检查计算机名,如果是乱码,改一下名字 2)有杀毒软件,能关则关 但是最好征求用户的同意 3)装两个一起解压databa ...
- 前端面试题常考&必考之--用jquery写出当前元素的同辈元素的第二个结点的value值
问题:用jquery写出当前元素的同辈元素的第二个结点的value值??? 分析:该题目有一个坑,那就是,如果当前元素没有第二个兄弟结点呢(坑坑坑) 解析: 一般我们可能会这样写: $(this).s ...
- SQL把a表字段数据存到b表字段 update,,insert
update SYS_Navigation set SYS_Navigation.PARENT_XH = SYS_Power_menu.parent_id,SYS_Navigation.web_tit ...
- Eclipse设置类和方法的注释模板
一.打开设置模板的窗口:Window->Preference->Java->Code Style->Code Template展开Comments,最常用的就是类和方法的注释, ...
- Warning: Failed prop type: Invalid prop `value` supplied to `Picker`.报错问题
在使用antd的日期插件时,不留意就会报各种错误. 例如:Warning: Failed prop type: Invalid prop `value` supplied to `Picker`. 这 ...
- 牛客网 珂学送分( 期望DP )
题意 : 题目链接 分析 : 听队友说一般概率从前往后推.期望从后往前推......... #include<bits/stdc++.h> using namespace std; ; d ...
- 13 November
[HEOI2015] 定价 BZOJ 4027: 在市场上有很多商品的定价类似于 999 元.4999 元.8999 元这样.它们和 1000 元.5000 元和 9000 元并没有什么本质区别,但是 ...
- SpringBoot:运行原理探究
西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处!防君子不防小人,共勉! SpringBoot ...