`
java-mans
  • 浏览: 11711239 次
文章分类
社区版块
存档分类
最新评论

HDU 2128 Tempter of the Bone II(BFS)

 
阅读更多

转载请注明出处,谢谢 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;
}





分享到:
评论

相关推荐

    HDU图论题目分类

    * 题目1010:Tempter of the Bone,涉及到递归搜索的概念。 * 题目1016:Prime Ring Problem,涉及到递归搜索的概念。 * 题目1026:Ignatius and the Princess I,涉及到完全搜索的概念。 2. 图的遍历:深度优先...

    ACM.zip_visual c

    例如,"HDU1010 Tempter of the Bone.cpp"可能就是利用DFS解决了一种寻找最短路径或解谜的问题。 另一方面,广度优先搜索(BFS)则是一种从根节点开始,逐层搜索直至找到目标的算法。BFS通常用于找出图中两个节点的...

    bfs.rar_hdu

    题目“bfs.rar_hdu”暗示了这是一个关于广度优先搜索(Breadth-First Search, BFS)的问题,源自HDU(杭州电子科技大学)的在线编程竞赛平台。通常,这类题目会涉及图论或者树的遍历,考察算法实现和逻辑思维能力。 ...

    hdu.rar_hdu

    HDU(杭州电子科技大学在线评测系统)是一个深受程序员喜爱的在线编程练习平台,它提供了丰富的算法题目供用户挑战,帮助他们提升编程技能和算法理解能力。"hdu.rar_hdu"这个压缩包文件很可能是某位程序员整理的他在...

    HDU1019(2028)解题报告

    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...

    HDU题目java实现

    8. **图论与树**:HDU题目中可能涉及图的遍历(深度优先搜索DFS、广度优先搜索BFS)、树的遍历(前序、中序、后序)以及最小生成树、最短路径等算法。 9. **动态规划**:这是一种优化策略,通过构建状态转移方程来...

    HDU_2010.rar_hdu 2010_hdu 20_hdu acm20

    【标题】"HDU_2010.rar"是一个压缩包文件,其中包含了与"HDU 2010"相关的资源,特别是针对"HDU ACM20"比赛的编程题目。"hdu 2010"和"hdu 20"可能是该比赛的不同简称或分类,而"hdu acm20"可能指的是该赛事的第20届...

    code_hdu.rar_ACM_The First_hdu_test case example

    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.rar_HDU 1089.cpp_OJ题求和_hdu_horsekw5_杭电obj" 提供的信息是关于一个压缩文件,其中包含了一个名为 "HDU 1089.cpp" 的源代码文件,这个文件是为了解决杭州电子科技大学(Hangzhou Dianzi ...

    ACM HDU题目分类

    ACM HDU 题目分类 ACM HDU 题目分类是指对 HDU 在线判题系统中题目的分类,总结了大约十来个分类。这些分类将有助于编程选手更好地理解和解决问题。 DP 问题 DP(Dynamic Programming,动态规划)是一种非常重要...

    hdu1250高精度加法

    ### hdu1250高精度加法 #### 背景介绍 在计算机科学与编程竞赛中,处理大整数运算(特别是加法、减法、乘法等)是常见的需求之一。当数字的位数超过了标准数据类型(如`int`、`long`等)所能表示的最大值时,就需要...

    HDU DP动态规划

    【标题】"HDU DP动态规划"涉及到的是在算法领域中的动态规划(Dynamic Programming,简称DP)技术,这是解决复杂问题的一种高效方法,尤其适用于有重叠子问题和最优子结构的问题。动态规划通常用于优化多阶段决策...

    Hdu1000—2169部分代码

    HDU是杭州电子科技大学(Hangzhou Dianzi University)举办的一个在线编程竞赛平台,全称为HDU Online Judge。ACM是国际大学生程序设计竞赛(International Collegiate Programming Contest)的缩写,是一个全球性的...

    HDU1059的代码

    HDU1059的代码

    hdu1001解题报告

    hdu1001解题报告

    hdu 1574 passed sorce

    hdu 1574 passed sorce

    hdu acm 教案(7)

    HDU ACM教案是针对ACM/ICPC(国际大学生程序设计竞赛)的训练教程,旨在帮助参赛者提升算法和编程技能。"搜索入门"这部分内容是教程中的一个重要章节,主要介绍在解决算法问题时如何有效地运用搜索策略。在这个章节...

    hdu2101解决方案

    hdu2101AC代码

    ACM HDU

    【ACM HDU】指的是在ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest)中,参赛者在杭州电子科技大学(Hangzhou Dianzi University,简称HDU)的在线评测系统上完成并已解决的题目集合...

    搜索bfs,dfs

    在提供的资源中,"HDUACM201603版_09)搜索入门.ppt"可能包含了对这两种搜索策略的详细讲解,包括它们的定义、算法实现、优缺点以及在实际问题中的应用案例。通过学习这份资料,你可以深入理解BFS和DFS的工作原理,...

Global site tag (gtag.js) - Google Analytics