• BZOJ3393 [Usaco2009 Jan]Laserphones 激光通讯 BFS


    原文链接http://www.cnblogs.com/zhouzhendong/p/8371735.html


    题目传送门 - BZOJ3393


    题意概括

      直接看原题的翻译吧,很容易懂的。

      


    题解

      我不知道这道题为什么放在网络流里面。

      我也不知道网上为什么几乎都是SPFA。

      这题就是一个裸的广搜啊啊啊。

      20ms通过。

      我们来考虑广搜。

      只有改变方向是要花费的。

      所以,我们入队的时候是一条线上的一起入队。

      具体看我的pushnew函数。

      然后主要的BFS循环内,只要扩展转弯就可以了(参见代码)。

      我们考虑到,我这样做会导致在一个位置上进行多次转弯。

      多次转弯,貌似是错的,但是由于本题特殊,这样一定是亏的,不会作为最优方案。

      大概分成两种情况。

      我们考虑如果只转了一次,显然是对的。

      如果转了3次及以上,显然是亏的。

      如果转了2次,只有可能:

        1.原方向行进,显然是亏的。

        2.原路返回,显然也是亏的。(自己脑补一下)

      还有一个疑惑:比如下图的路线是否可能为最优路线(我的算法有可能会搜出这样的路线):

      

      于是在(0,5)这个位置的镜子显然不对了。

      但是这个显然不会是最优路线,直接挂掉。


    代码

    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    const int WH=105,N=4*WH*WH;
    int w,h,S,E,dis[N],vis[N],q[N],head,tail;
    char g[WH][WH];
    int dx[4]={-1, 0, 1, 0};
    int dy[4]={ 0, 1, 0,-1};
    char gc(){
    	char ch=getchar();
    	while (ch!='.'&&ch!='*'&&ch!='C')
    		ch=getchar();
    	return ch;
    }
    bool check(int x,int y){
    	return 1<=x&&x<=w&&1<=y&&y<=h&&g[x][y]!='*';
    }
    int HA(int dir,int x,int y){
    	return dir*w*h+(x-1)*h+y-1;
    }
    void HB(int v,int &dir,int &x,int &y){
    	dir=v/w/h,v%=w*h,x=v/h+1,y=v%h+1;
    }
    bool covered(int v1,int v2){
    	return v1%(w*h)==v2%(w*h);
    }
    void pushnew(int dir,int x,int y,int d){
    	while (check(x,y)){
    		int i=HA(dir,x,y);
    		if (vis[i])
    			break;
    		vis[i]=1,dis[i]=d;
    		q[++tail]=i;
    		x+=dx[dir],y+=dy[dir];
    	}
    }
    int main(){
    	scanf("%d%d",&h,&w);
    	for (int i=1;i<=w;i++)
    		for (int j=1;j<=h;j++)
    			g[i][j]=gc();
    	S=E=-1;
    	for (int i=1;i<=w;i++)
    		for (int j=1;j<=h;j++)
    			if (g[i][j]=='C')
    				if (!~S)
    					S=(i-1)*h+j-1;
    				else
    					E=(i-1)*h+j-1;
    	memset(vis,0,sizeof vis);
    	head=tail=0;
    	for (int i=0;i<4;i++)
    		dis[HA(i,E/h+1,E%h+1)]=w*h;
    	for (int i=0;i<4;i++)
    		pushnew(i,S/h+1,S%h+1,0);
    	while (head<tail){
    		int v=q[++head],dir,x,y;
    		if (covered(v,E))
    			break;
    		HB(v,dir,x,y);
    		pushnew((dir+1)%4,x,y,dis[v]+1);
    		pushnew((dir+3)%4,x,y,dis[v]+1);
    	}
    	int ans=w*h;
    	for (int i=0;i<4;i++)
    		ans=min(ans,dis[HA(i,E/h+1,E%h+1)]);
    	printf("%d",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    SCU3033 Destroying a Painting(最小费用最大流)
    HDU4859 海岸线(最小割)
    ZOJ3228 Searching the String(AC自动机)
    HUST1024 dance party(最大流)
    SGU438 The Glorious Karlutka River =)(最大流)
    SPOJ839 Optimal Marks(最小割)
    BZOJ1086 [SCOI2005]王室联邦(树分块)
    SCU3109 Space flight(最大权闭合子图)
    HDU3138 Coconuts(最小割)
    ZOJ2539 Energy Minimization(最小割)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3393.html
Copyright © 2020-2023  润新知