【BZOJ】1687: [Usaco2005 Open]Navigating the City 城市交通(bfs)

http://www.lydsy.com/JudgeOnline/problem.php?id=1687

bfs后然后逆向找图即可。因为题目保证最短路唯一

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr2(a, b, c) for1(i, 1, b) { for1(j, 1, c) cout << a[i][j]; cout << endl; }
#define printarr1(a, b) for1(i, 1, b) cout << a[i]; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }

const int N=100, Q=N*N, dx[]={-1, 1, 0, 0}, dy[]={0, 0, -1, 1};
int mp[N][N], n, m, f[N][N], front, tail, ans1[N], ans2[N], cnt, X, Y, XX, YY;
char s[N];
struct dat { int x, y; }q[Q];
void bfs() {
	front=tail=0;
	q[tail].x=X, q[tail++].y=Y;
	CC(f, 0x3f); f[X][Y]=0;
	while(tail!=front) {
		dat &t=q[front++]; if(front==Q) front=0;
		int x=t.x, y=t.y, d=f[x][y];
		rep(i, 4) {
			int fx=dx[i]+x, fy=dy[i]+y;
			if(fx<1 || fy<1 || fx>n || fy>m || !mp[fx][fy] || f[fx][fy]<=d+1) continue;
			f[fx][fy]=d+1;
			q[tail].x=fx, q[tail++].y=fy; if(tail==Q) tail=0;
		}
	}
	int x=XX, y=YY, now=-1, tot=0;
	while(!(x==X && y==Y)) {
		rep(i, 4) {
			int fx=dx[i]+x, fy=dy[i]+y;
			if(fx<1 || fy<1 || fx>n || fy>m || !mp[fx][fy] || f[fx][fy]!=f[x][y]-1) continue;
			if(mp[fx][fy]==1) ++tot;
			if(now!=i && now!=-1) {
				ans1[++cnt]=now;
				ans2[cnt]=tot;
				tot=0;
			}
			now=i;
			x=fx, y=fy;
		}
	}
	ans1[++cnt]=now; ans2[cnt]=tot+1;
}

int main() {
	read(n); read(m); n=n*2-1, m=m*2-1;
	for1(i, 1, n) {
		scanf("%s", s+1);
		for1(j, 1, m) {
			if(s[j]=='+') mp[i][j]=1;
			else if(s[j]=='S') X=i, Y=j, mp[i][j]=3;
			else if(s[j]=='E') XX=i, YY=j, mp[i][j]=4;
			else if(s[j]=='.') mp[i][j]=0;
			else mp[i][j]=2;
		}
	}
	bfs();
	for3(i, cnt, 1) {
		char c='H';
		if(ans1[i]==2) c='E';
		else if(ans1[i]==3) c='W';
		else if(ans1[i]==1) c='N';
		else if(ans1[i]==0) c='S';
		printf("%c %d\n", c, ans2[i]);
	}
	return 0;
}

 

 


 

 

Description

    由于牛奶市场的需求,奶牛必须前往城市,但是唯一可用的交通工具是出租车.教会奶牛如何在城市里打的.
    给出一个城市地图,东西街区E(1≤E≤40),南北街区N(1≤N≤30).制作一个开车指南给 出租车司机,告诉他如何从起点(用S表示)到终点(用E表示).每一个条目用空格分成两部分,第一个部分是方向(N,E,S,W之一),第二个是一个整 数,表示要沿着这个方向开几个十字路口.如果存在多条路线,你应该给出最短的.数据保证,最短的路径存在且唯一.    地图中“+”表示十字路口,道路 用“I”和“一”表示.建筑和其他设施用“.”表示.下面是一张地图:
 
 
    出租车可以沿着东,北,西,北,东开两个十字路口,以此类推.具体将由样例给出

Input

    第1行:两个用空格隔开的整数N和E.

    第2到2N行:每行有2E-I个字符,表示地图.

Output

    每行有一个表示方向的字母和一个表示要开几个十字路口的数字表示.

Sample Input

 

Sample Input

 

Sample Output

E 1
N 1
W 1
N 1
E 2
S 1
E 3
S 1
W 1

HINT

Source

posted @ 2014-09-20 13:47  iwtwiioi  阅读(241)  评论(0编辑  收藏  举报