BZOJ3393 [Usaco2009 Jan]Laserphones 激光通讯 BFS

Posted tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

  

以上是关于BZOJ3393 [Usaco2009 Jan]Laserphones 激光通讯 BFS的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj3396] [Usaco2009 Jan]Total flow 水流

bzoj 1575: [Usaco2009 Jan]气象牛Baricdp

bzoj 3396: [Usaco2009 Jan]Total flow 水流最大流

[BZOJ1575] [Usaco2009 Jan]气象牛Baric(DP)

[BZOJ1574] [Usaco2009 Jan]地震损坏Damage(贪心 + dfs)

BZOJ1576 [Usaco2009 Jan]安全路经Travel