zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    前端之页面标签的图标修改
    分页, 解析器, 渲染器
    DRF的认证,频率,权限
    视图组件,路由组件,版本控制
    序列化组件
    Restful规范
    docker大全集
    哨兵和docker容器
    项目发布须知
    Linux之nginx
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3393.html
Copyright © 2011-2022 走看看