HDU ACM 1044 Collect More Jewels BFS+DFS

题意:在一个迷宫中,有一些宝物,从起点走到终点,问在给定的时间内,到达终点后所能拾取珠宝的最大价值。

分析(BFS+DFS):

1、求入口到第一个取宝物的地方的最短距离

2、求第i个取宝物的地方到第i+1个取宝物的地方的最短距离

3、求第n个取宝物的地方到出口的最短距离

4、保证以上3点能在时间L内实现的情况下,取得的宝石价值最大。

BFS特点:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元来存储状态)

DFS特点:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高。

对整个图做bfs,bfs求得某个点(入口、出口、珠宝)到另外一个点之间的最短距离。bfs过程中构建隐式图,然后从入口处开始进行dfs搜索构造的隐式图,更新ans。

PS:该題还能用BFS+状态压缩做,但效率不高。

将宝物状态压缩,对于l个珍宝,可以用l位二进制表示珍宝的获取情况(1表示获得,0未获得)。然后用vis[i][j][k]表示状态,i表示珍宝获取情况,(j,k)表示位置。这样相当于走2^l张地图,每次得到珍宝时转换地图,这样就需要相当多的时间消耗了。在bfs+dfs中,珍宝至多10件,可以找出起点到所有珍宝和终点的最短路径,珍宝到其他珍宝和终点的最短路径。需要bfs地图至多21次,比上面的2^l次要少很多。因此BFS+DFS效率高。

#include<iostream>
#include<queue>
using namespace std;

#define N 60
int W,H,L,M;   //地图是W列H行,时间限制L,宝石数量M
int val[N];      //宝石的价值
char map[N][N];  //地图
bool bfsvis[N][N];   //BFS访问标记
bool dfsvis[N];   //dfs访问标记
int step[N][N];      //bfs中访问步长

int ans,sum;        //结果,宝石总价值
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
int dis[N][N];       //记录开始位置,结束位置,各宝石位置两两之间的距离

void BFS(int cx,int cy,int s) //求解(cx,cy)到其他点的距离,s(0-M+1),0表示开始位置,M+1出口,其他宝石位置
{
	queue<int> q;
	int u,i,x,y,x2,y2;

	memset(bfsvis,false,sizeof(bfsvis));
	memset(step,0,sizeof(step));
	u=cx*W+cy;      //初始点
	q.push(u);
	bfsvis[cx][cy]=true;
	step[cx][cy]=0;
	while(!q.empty())
	{
		u=q.front();
		q.pop();
		x=u/W;
		y=u%W;
		for(i=0;i<4;i++)      //四个方向
		{
			x2=x+dir[i][0];
			y2=y+dir[i][1];
			if(x2<0||x2>=H||y2<0||y2>=W||bfsvis[x2][y2]||map[x2][y2]=='*')
				continue;
			bfsvis[x2][y2]=true;
			step[x2][y2]=step[x][y]+1;    //步长加1
			if(map[x2][y2]=='@') dis[s][0]=step[x2][y2];  //其他点到起点
			else if(map[x2][y2]=='<') dis[s][M+1]=step[x2][y2]; //其他点到终点
			else if(map[x2][y2]>='A' && map[x2][y2]<='J')  //其他点到宝石点
				dis[s][map[x2][y2]-'A'+1]=step[x2][y2];
			q.push(x2*W+y2);
		}
	}
}

void DFS(int s,int value,int t) //s当前点,value当前获得的价值,t当前花费的时间
{
	int i;

	if(t>L)        //超时
		return ;
	if(ans==sum)   //宝石已全部获取,剪枝
		return ;
	if(s>M)        //已到出口
	{
		if(value>ans)
			ans=value;
		return ;
	}
	for(i=0;i<=M+1;i++)
	{
		if(dis[s][i]==0 || dfsvis[i]) //自己到自己或者已经访问过
			continue;
		dfsvis[i]=true;
		DFS(i,value+val[i],t+dis[s][i]);
		dfsvis[i]=false;
	}
}

int main()
{
	int T,i,j,t=0;

	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d%d%d",&W,&H,&L,&M);
		sum=0;
		for(i=1;i<=M;i++)
		{
			scanf("%d",&val[i]);
			sum+=val[i];
		}
		val[0]=val[M+1]=0;
		for(i=0;i<H;i++)
			scanf("%s",map[i]);
		memset(dis,0,sizeof(dis));
		for(i=0;i<H;i++)                //BFS对相关点处理
			for(j=0;j<W;j++)
				if(map[i][j]=='@')
					BFS(i,j,0);
				else if(map[i][j]=='<')
					BFS(i,j,M+1);
				else if(map[i][j]>='A' && map[i][j]<='Z')
					BFS(i,j,map[i][j]-'A'+1);
		ans=-1;
		memset(dfsvis,false,sizeof(dfsvis));
		dfsvis[0]=true;
		DFS(0,0,0);
		cout<<"Case "<<++t<<":"<<endl;
		if(ans>=0)
			cout<<"The best score is "<<ans<<"."<<endl;
		else
			cout<<"Impossible"<<endl;
		if(T>0)
			cout<<endl;
	}
    return 0;
}
时间: 2024-08-21 16:11:03

HDU ACM 1044 Collect More Jewels BFS+DFS的相关文章

hdu.1044.Collect More Jewels(bfs + 状态压缩)

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5345    Accepted Submission(s): 1189 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

HDU 1044 Collect More Jewels 【经典BFS+DFS】

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6597    Accepted Submission(s): 1527 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

HDU 1044 Collect More Jewels【BFS+DFS+建立距离图】

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6707    Accepted Submission(s): 1556 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

1044 [Collect More Jewels] DFS+BFS

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1044 题目大意:在地图中,有M个宝石,每个宝石有不同价值.问在时间限制L之内,从入口到出口这一路上获得的最大价值是多少.拿宝石不额外花时间,走一格用时为1. 关键思想:考虑到BFS和DFS的特点,BFS在解决最短(小)问题是很有效,但内存耗费巨大:DFS可以解决绝大多数搜索问题,但层数较深时,时间开销和栈的开销都很大. 这道题,只用DFS显然是不行的,地图比较大了.但是只用BFS也不行,因为取完之后

hdu 1044 Collect More Jewels

并没有做过这种类型的题目,不太会做...看了一下大神的代码,然后自己敲...额..思路一样了,代码也差不多.. http://www.cnblogs.com/kuangbin/archive/2012/08/14/2637512.html 先通过BFS预处理任意两点之间的距离,然后通过DFS暴力模拟路径,算出最优解. 感觉自己可能对BFS理解比DFS更深一点,或者说,BFS比较简单一点吧... 这题还有一种解法是状态压缩+BFS...通过开设一个int型变量记录是否拿到宝物,然后暴力..不过这种

HDU ACM 1495 非常可乐(广搜BFS)

非常可乐 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 42   Accepted Submission(s) : 21 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却

HDU ACM 1043 Eight-&gt;广度优先搜索(BFS)+康托展开(全排列hash)实践

分析:经典的八数码问题,参考别人的代码写的,逆向广搜,把结果保存起来,之后在使用. #include<iostream> #include<queue> using namespace std; #define STATE_COUNT 363000 //因为9!=362880 int fact[]={1,1,2,6,24,120,720,5040,40320,362880}; //0到9的阶乘,用来计算hash值 char dir[4][2]={ {0,1},{0,-1},{1,0

HDU ACM 2181 哈密顿绕行世界问题-&gt;DFS(深度有限搜索)

分析:DFS即可. #include<iostream> using namespace std; bool map[21][21]; bool vis[21]; int ans[21],num,m; void init() { int i,a; memset(map,false,sizeof(map)); for(i=1;i<=20;i++) //构图 { map[i][cin>>a,a]=true; map[i][cin>>a,a]=true; map[i][

HDU Collect More Jewels 1044

BFS + 状态压缩 险过 这个并不是最好的算法 但是写起来比较简单 , 可以AC,但是耗时比较多 下面是代码 就不多说了 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; #define Max(a,b) (a>b?a:b) #define Min(a,b) (a