转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=2128
这题出现在BFS专题里,是yobobobo提出做的,我便看了看,中途也和yobobobo讨论了许多,得到一些启发
这题网上好多的BFS代码都是错的,HDOJ的数据比较弱
题目意思不难理解,取一些,炸开一些墙以最快的速度找到出口。由于有最短时间的问题,首选就是BFS了,其实后来想想也许用DFS早就解决了。
如果用BFS的话状态表示以及判重会有很大问题,一开始觉得flag[x][y][bomb]判重就够了,其实不然,相同的bomb数量其实状态是不一样的,
后来想到由于会炸掉一些墙,会取走一些,就得传递整个图。一下子在结点里放放入两个二维数组,想了想地图不是很大,应该不 会MLE,
那么在flag[x][y][bomb]每个状态取最小的步数的情况,最终必然是WA了,因为步数越小不一定是最佳,还要牵扯整个图的情况。于是想到用整
张图来判重,vector<Node>flag[x][y][bomb]来判重,结点里还有二维数组,YY了半天之后,提交果断是MLE,之前在和yobobobo讨论的时候
便想到了二进制压缩状态保存整个图,因为8*8刚好64位整数可以保存,而且不论是墙还是个数都少于64,果断改成二进制压缩,注意一些细节之后
测了许多数据没问题提交还是WA,不过果断发现是位运算溢出了,囧,再提交还是WA,一下子陷入悲剧当中。不断修改,各种错误都出来了,MLE
WA,TLE,都是由于状态判重部分导致。最后仔细一看题,发现是0 0结束,我却一直只是判断EOF,囧死,终于AC。
艰难的一题啊,不过yobobobo的探索精神令人感动,加油啊!!!
代码里有注释,另外附上一组数据
6 5
S.XX1
X.1X1
XX.X.
XXXXX
XXXXX
XXXDX
答案是17并不是-1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define LL unsigned long long
using namespace std;
int n,m;
int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; //BFS四个方向
char mmap[10][10]; //原始地图
int wallcnt,wallmap[10][10]; //原始地图上墙的数量,以及分布图,对于每个墙给个编号
int bombcnt,bombmap[10][10]; //原始地图上的数量,以及分布图,对于每个给个编号
struct Node{
int x,y,step,bomb; //位置,步数,剩余
LL vis; //地图上的已取情况,1表示某处已取
LL wall; //地图上剩余墙的情况,1表示某处还有墙
bool check(){ //判断是否在地图范围内
if(x>=0&&y>=0&&x<n&&y<m)
return true;
return false;
} //优先队列
bool operator<(const Node n1) const{
return step>n1.step;
}
}s,e,u,v;
vector<Node>flag[8][8][8*8*9+1]; //判重,flag[x][y][z]表示 在(x,y)处手上有z个时的状态
bool check(Node tmp){ //判断是否和之前已入队的情况相同
for(int i=0;i<flag[tmp.x][tmp.y][tmp.bomb].size();i++)
if(tmp.wall==flag[tmp.x][tmp.y][tmp.bomb][i].wall&&tmp.vis==flag[tmp.x][tmp.y][tmp.bomb][i].vis) //结点剩余的墙情况以及情况完全相同
return false;
return true;
}
int bfs(){
priority_queue<Node>que;
que.push(s);
while(!que.empty()){
u=que.top();
que.pop();
for(int i=0;i<4;i++){
v=u;
v.step++;
v.x=u.x+way[i][0];
v.y=u.y+way[i][1];
if(v.check()){
if(mmap[v.x][v.y]=='D') //找到终点
return v.step;
if(mmap[v.x][v.y]=='X'&&((1LL<<wallmap[v.x][v.y])&v.wall)){ //某处原来是墙,而且也没被炸毁
if(v.bomb>0){ //手上有
v.bomb--;
v.step++;
v.wall^=(1LL<<wallmap[v.x][v.y]); //标记下,已经被炸毁
que.push(v); //结点入队
flag[v.x][v.y][v.bomb].push_back(v); //保存状态
}
}
else if(mmap[v.x][v.y]>='1'&&mmap[v.x][v.y]<='9'&&(v.vis&(1LL<<bombmap[v.x][v.y]))==0){ //某处是,而且之前没有取
v.bomb+=mmap[v.x][v.y]-'0'; //取
v.vis|=(1LL<<bombmap[v.x][v.y]); //标记已取
que.push(v); //结点入队
flag[v.x][v.y][v.bomb].push_back(v); //保存状态
}
else{
if(flag[v.x][v.y][v.bomb].empty()||check(v)){ //当前没有状态或者和之前的状态都不相同
flag[v.x][v.y][v.bomb].push_back(v); //保存
que.push(v); //入队
}
}
}
}
}
return -1;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF&&n+m){
for(int i=0;i<n;i++) //判重初始化
for(int j=0;j<m;j++)
for(int k=0;k<=(n*m*9);k++)
if(!flag[i][j][k].empty())
flag[i][j][k].clear();
bombcnt=wallcnt=0;
memset(wallmap,-1,sizeof(wallmap));
memset(bombmap,-1,sizeof(bombmap));
for(int i=0;i<n;i++){
scanf("%s",mmap[i]);
for(int j=0;j<m;j++)
if(mmap[i][j]=='S'){ //起点标记
s.x=i;
s.y=j;
s.step=0;
s.bomb=0;
s.vis=0;
}
else if(mmap[i][j]=='X')
wallmap[i][j]=wallcnt++; //对于每个墙给个编号
else if(mmap[i][j]>='1'&&mmap[i][j]<='9')
bombmap[i][j]=bombcnt++; //对于每个位置给个编号
}
s.wall=(1LL<<wallcnt)-1; //初始化,所有墙都没有被炸
printf("%d\n",bfs());
}
return 0;
}
分享到:
相关推荐
* 题目1010:Tempter of the Bone,涉及到递归搜索的概念。 * 题目1016:Prime Ring Problem,涉及到递归搜索的概念。 * 题目1026:Ignatius and the Princess I,涉及到完全搜索的概念。 2. 图的遍历:深度优先...
例如,"HDU1010 Tempter of the Bone.cpp"可能就是利用DFS解决了一种寻找最短路径或解谜的问题。 另一方面,广度优先搜索(BFS)则是一种从根节点开始,逐层搜索直至找到目标的算法。BFS通常用于找出图中两个节点的...
题目“bfs.rar_hdu”暗示了这是一个关于广度优先搜索(Breadth-First Search, BFS)的问题,源自HDU(杭州电子科技大学)的在线编程竞赛平台。通常,这类题目会涉及图论或者树的遍历,考察算法实现和逻辑思维能力。 ...
HDU(杭州电子科技大学在线评测系统)是一个深受程序员喜爱的在线编程练习平台,它提供了丰富的算法题目供用户挑战,帮助他们提升编程技能和算法理解能力。"hdu.rar_hdu"这个压缩包文件很可能是某位程序员整理的他在...
The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is 105. Input Input...
8. **图论与树**:HDU题目中可能涉及图的遍历(深度优先搜索DFS、广度优先搜索BFS)、树的遍历(前序、中序、后序)以及最小生成树、最短路径等算法。 9. **动态规划**:这是一种优化策略,通过构建状态转移方程来...
【标题】"HDU_2010.rar"是一个压缩包文件,其中包含了与"HDU 2010"相关的资源,特别是针对"HDU ACM20"比赛的编程题目。"hdu 2010"和"hdu 20"可能是该比赛的不同简称或分类,而"hdu acm20"可能指的是该赛事的第20届...
The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases. In each test case, there are two integers k,m(1≤k≤1018,1≤m≤100). Output For each test case, print ...
【标题】"hdu.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj" 提供的信息是关于一个压缩文件,其中包含了一个名为 "HDU 1089.cpp" 的源代码文件,这个文件是为了解决杭州电子科技大学(Hangzhou Dianzi ...
ACM HDU 题目分类 ACM HDU 题目分类是指对 HDU 在线判题系统中题目的分类,总结了大约十来个分类。这些分类将有助于编程选手更好地理解和解决问题。 DP 问题 DP(Dynamic Programming,动态规划)是一种非常重要...
### hdu1250高精度加法 #### 背景介绍 在计算机科学与编程竞赛中,处理大整数运算(特别是加法、减法、乘法等)是常见的需求之一。当数字的位数超过了标准数据类型(如`int`、`long`等)所能表示的最大值时,就需要...
【标题】"HDU DP动态规划"涉及到的是在算法领域中的动态规划(Dynamic Programming,简称DP)技术,这是解决复杂问题的一种高效方法,尤其适用于有重叠子问题和最优子结构的问题。动态规划通常用于优化多阶段决策...
HDU是杭州电子科技大学(Hangzhou Dianzi University)举办的一个在线编程竞赛平台,全称为HDU Online Judge。ACM是国际大学生程序设计竞赛(International Collegiate Programming Contest)的缩写,是一个全球性的...
HDU1059的代码
hdu1001解题报告
hdu 1574 passed sorce
HDU ACM教案是针对ACM/ICPC(国际大学生程序设计竞赛)的训练教程,旨在帮助参赛者提升算法和编程技能。"搜索入门"这部分内容是教程中的一个重要章节,主要介绍在解决算法问题时如何有效地运用搜索策略。在这个章节...
hdu2101AC代码
【ACM HDU】指的是在ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest)中,参赛者在杭州电子科技大学(Hangzhou Dianzi University,简称HDU)的在线评测系统上完成并已解决的题目集合...
在提供的资源中,"HDUACM201603版_09)搜索入门.ppt"可能包含了对这两种搜索策略的详细讲解,包括它们的定义、算法实现、优缺点以及在实际问题中的应用案例。通过学习这份资料,你可以深入理解BFS和DFS的工作原理,...