zoukankan      html  css  js  c++  java
  • 【POJ3182】The Grove BFS 最短路径周围

        意甲冠军:给定一个N*M图。,间‘X’代表树木(树木必须汇集到森林,非分离),然后,‘.’它代表的空间。‘*’它代表的起点。现在它需要从起点。一圈,最后回到起点,所经过最少点数。

        题目中给的‘+’就是当中一种最短路径。

        题解:随便找一条经过森林且不经过起点的直线,可证路径一定会穿过这条直线。那么就在这条直线上枚举一个点,做两遍BFS,求其从分别直线两側出发到起点的最短距离。


        在这里说一个推断边界的简单方法,就是先给图里每一个点打上标记。详见代码里‘in’数组。in值为0的自然就不再里面,而没有必要推断什么“1<=x&&x<=n&&……”。


        好了,贴代码。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 55
    #define inf 0x3f3f3f3f
    using namespace std;
    const int dx[8]={-1,-1,-1,0,0,1,1,1};
    const int dy[8]={-1,0,1,-1,1,-1,0,1};
    struct Lux
    {
    	int x,y;
    	Lux(int a,int b):x(a),y(b){}
    	Lux(){}
    };
    char mp[N][N];
    int map[N][N];/*0可行,1森林,2枚举线段,3起点*/
    int n,m,ans=inf;
    int dist[N][N],tx,ty;
    
    int in[N][N],cnt;
    queue<Lux>q;
    int bfs(int sx,int sy)
    {
    	int i,fr,ret;
    	int vx,vy;
    
    	for(ret=fr=0;fr<2;fr++)
    	{
    		memset(dist,0x3f,sizeof(dist));
    		while(!q.empty())q.pop();
    		for(i=fr*5;i<fr*5+3;i++)
    		{
    			vx=sx+dx[i];
    			vy=sy+dy[i];
    			if(in[vx][vy]&&!map[vx][vy])dist[vx][vy]=1,q.push(Lux(vx,vy));
    		}
    		while(!q.empty())
    		{
    			Lux U=q.front();q.pop();
    			for(i=0;i<8;i++)
    			{
    				vx=U.x+dx[i];
    				vy=U.y+dy[i];
    				if(in[vx][vy]&&!map[vx][vy]&&dist[vx][vy]>dist[U.x][U.y]+1)
    				{
    					dist[vx][vy]=dist[U.x][U.y]+1;
    					q.push(Lux(vx,vy));
    				}
    			}
    		}
    		ret+=dist[tx][ty];
    	}
    	return ret;
    }
    int main()
    {
    //	freopen("test.in","r",stdin);
    	int i,j,x,y;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)scanf("%s",mp[i]+1);
    	for(j=1;j<=m;j++)for(i=1;i<=n;i++)
    	{
    		in[i][j]=++cnt;
    		if(mp[i][j]=='X')
    		{
    			map[i][j]=1;
    			x=i;y=j;
    		}
    		else if(mp[i][j]=='*')tx=i,ty=j;
    	}
    	if(tx==x&&ty>y)
    	{
    		for(i=y;mp[x][i]=='X';i--);
    		y=i;
    		for(i=y;i;i--)map[x][i]=3;
    		for(i=y;i;i--)ans=max(ans,bfs(x,i));
    	}
    	else
    	{
    		for(i=y+1;i<=m;i++)map[x][i]=3;
    		for(i=y+1;i<=m;i++)ans=min(ans,bfs(x,i));
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    



    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    office文件在线预览,模仿网易邮箱在线预览的
    SQLServer加入域后无法远程连接
    c#将金额转换为大写,支持小数点,原创经典
    GridView多行标题行、改造标题行、自定义标题行完美版
    汇编语言常用指令
    Nature重磅:Hinton、LeCun、Bengio三巨头权威科普深度学习
    微软新技术证明深度学习还能更“深入”
    几个激光的驱动
    rplidar跑cartographer
    Git常用命令速查表
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4905443.html
Copyright © 2011-2022 走看看