HDU 4771 Stealing Harry Potter's Precious

本文介绍了一种寻宝路径规划算法,通过BFS找到每个宝藏点间的最短路径,并使用DFS进行路径顺序优化,最终确定获取所有宝藏的最短总距离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意是给你一个起点@,.为可走,#为不可走,再给你一些宝藏的坐标,问取完这些宝藏需要的最短距离是多少,如果不能输出-1.

个人认为模拟题最重要的是划分步骤,现在我们来理一理这道题的步骤。

第一步寻找每一个宝藏点到下一个点的最短路,对于每个起点通过bfs实现。

第二步判断路径的先后顺序,这里可以通过dfs,进行2的n次方枚举,数据范围小便可以完成。

这就将一个模拟题拆分为两个子问题,一步一步写便可以完成。

下附AC代码。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#define maxn 150
using namespace std;
struct nod
{
	int x,y;
	nod(int a,int b)
	{
		x=a;
		y=b;
	}
	nod(){}	
}val[maxn];
int n,m,qq,cnt;
queue<nod> q;
int ans=987654321;
int valnum[maxn][maxn];
int num[maxn][maxn];
char gra[maxn][maxn];
int vis[maxn][maxn][maxn];
int dis[maxn][maxn][maxn];
int fx[]={0,1,-1,0,0};
int fy[]={0,0,0,1,-1};
void bfs(int x,int y,int num)
{
	while(!q.empty())
	q.pop();
	q.push(nod(x,y));
	vis[num][x][y]=1;
	dis[num][x][y]=0;
	while(!q.empty())
	{
		nod now=q.front();
		q.pop();
		for(int i=1;i<=4;i++)
		{
			int nx=now.x+fx[i];
			int ny=now.y+fy[i];
			if(1<=nx && nx<=n && 1<=ny && ny<=m && gra[nx][ny]=='.' && vis[num][nx][ny]==0)
			{
				vis[num][nx][ny]=1;
				dis[num][nx][ny]=dis[num][now.x][now.y]+1;
				q.push(nod(nx,ny));
			}
		}
	}
}
void dfs(int x,int y,int lef[],int now)
{
	int flag=true; 
	for(int i=1;i<=qq;i++)
	{
		if(lef[i])
		{
			flag=false;
			break;
		}
	}
	if(flag==true)
	{
		ans=min(ans,now);
		return;
	}
	
	for(int i=1;i<=4;i++)
	if(lef[i])
	{
		int d=dis[valnum[x][y]][val[i].x][val[i].y];
		if(d!=-1)
		{
			lef[i]=0;
			dfs(val[i].x,val[i].y,lef,now+d);
			lef[i]=1;
		}
	}
}
int main()
{
	while(cin>>n>>m && (n||m))
	{
		ans=987654321;
		memset(vis,0,sizeof(vis));
		memset(dis,-1,sizeof(dis));
		cnt=0;
		int nx,ny;
		for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			cin>>gra[i][j];
			cnt++;
			num[i][j]=cnt;
			if(gra[i][j]=='@')
			nx=i,ny=j;
		}
		valnum[nx][ny]=0;
		bfs(nx,ny,0);
		cin>>qq;
		for(int i=1;i<=qq;i++)
		{
			int x,y;
			cin>>x>>y;
			val[i].x=x;
			val[i].y=y;
			valnum[x][y]=i;
			bfs(x,y,i);
		}
		int temp[5];
		for(int i=1;i<=4;i++)
		temp[i]=1;
		dfs(nx,ny,temp,0);
		if(ans==987654321)
		cout<<"-1"<<endl;
		else 
		cout<<ans<<endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值