hdu 4771 Stealing Harry Potter's Precious(bfs+枚举)

注意,宝藏数最多只有4个,所有我们可以先用bfs搜索出宝藏加上起点两两间距离,然后在枚举走的顺序即可。

枚举顺序用next_permutation()函数比较方便


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
struct node
{
	int x,y;
	int step;
};
struct pos{
	int x,y;
}G[1000];
int maze[105][105];
bool en[105][105];
bool vis[105][105];
int dir[105][105];
int n,m;
int xx;
int sx,sy;
int ans=0;
vector <pair<int,int> > A;


int bfs(int x,int y,int ox,int oy)
{
	memset(vis,0,sizeof(vis));
	queue<node> q;
	node tmp;
	tmp.x=x,tmp.y=y;
	tmp.step=0;
	q.push(tmp);
	vis[x][y]=1;
	while(!q.empty())
	{
		node tmp=q.front();

		q.pop();
		
		if(tmp.x==ox&&tmp.y==oy) return tmp.step;
		for(int i=-1;i<=1;i++)
			for(int j=-1;j<=1;j++)
			{
				if(i+j==-1||i+j==1)
				{
					int x=tmp.x+i,y=tmp.y+j;
					if(!vis[x][y]&&maze[x][y]!=-1&&x>=1&&y>=1&&x<=n&&y<=m)
					{
						vis[x][y]=1;
						node tt;
						tt.x=x,tt.y=y,tt.step=tmp.step+1;
						q.push(tt);
					}
				}
			}
	}
	return -1;
}

int main()
{
	while(scanf("%d%d",&n,&m)&&(n||m))
	{
	
		ans=0;
		memset(maze,0,sizeof(maze));
		memset(en,0,sizeof(en));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;)
			{
				char ch;
				scanf("%c",&ch);
				if(ch=='#')
					maze[i][j]=-1,j++;
				else if(ch=='.'||ch=='@')
					maze[i][j]=0,j++;
				if(ch=='@')
				{
					sx=i,sy=j-1;
				}
			}
		}
	
		scanf("%d",&xx);
		for(int i=1;i<=xx;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			G[i].x=a;
			G[i].y=b;
			
		}
		G[0].x=sx;G[0].y=sy;
		for(int i=0;i<=xx;i++){
			for(int j=0;j<=xx;j++){
				dir[i][j]=bfs(G[i].x,G[i].y,G[j].x,G[j].y);
			}
		}
		
		int ord[100];
		for(int i=1;i<=xx;i++){
			ord[i]=i;
		}
		ord[0]=0;
		int res=100000000;
		do {
			int tmp=0;
			for(int i=0;i<xx;i++){
				tmp+=dir[ord[i]][ord[i+1]];
				if(dir[ord[i]][ord[i+1]]==-1) tmp=-1;
			}
			res=min(res,tmp);
		}while(next_permutation(ord+1,ord+xx+1));
		
		printf("%d\n",res);
	}
}


你可能感兴趣的:(bfs)