bzoj:1687;poj 2434:[Usaco2005 Open]Navigating the City 城市交通

Description

A dip in the milk market has forced the cows to move to the city. The only employment available is in the venerable field of taxi-driving. Help the cows learn their way around the city. 

Given a city map with E (1 <= E <= 40) east/west street locations and N (1 <= N <= 30) north/south street locations, create instructions for a taxi driver to navigate from the start of his route (marked 'S') to the end (marked 'E'). Each instruction is a direction (one of 'N', 'E', 'S', or 'W') followed by a space followed by an integer that tells how many blocks to drive in that direction. If multiple routes are available, your program should output the shortest route. The shortest route is guaranteed to exist and be unique. 

The map is depicted as a grid of '+'s that represent intersections and a set of roads depicted as '-' and '|'. Buildings and other obstacles are shown as '.'s. Here is a typical map: 
由于牛奶市场的需求,奶牛必须前往城市,但是唯一可用的交通工具是出租车.教会奶牛如何在城市里打的.
    给出一个城市地图,东西街区E(1≤E≤40),南北街区N(1≤N≤30).制作一个开车指南给出租车司机,告诉他如何从起点(用S表示)到终点(用E表示).每一个条目用空格分成两部分,第一个部分是方向(N,E,S,W之一),第二个是一个整数,表示要沿着这个方向开几个十字路口.如果存在多条路线,你应该给出最短的.数据保证,最短的路径存在且唯一.    地图中“+”表示十字路口,道路用“I”和“一”表示.建筑和其他设施用“.”表示.下面是一张地图:

+-+-+.+-+-+

|...|.....|
+-+.+-+-+-+
..|.......|
S-+-+-+.E-+

The taxi should go east, north, west, north, east two blocks, and so on. See the output format and sample solution below for its complete route.
出租车可以沿着东,北,西,北,东开两个十字路口,以此类推.具体将由样例给出

Input

* Line 1: Two space-separated integers, N and E. 

* Lines 2..2*N: These lines each contain 2*E-1 characters and encode the map of the street. Every other input line gives the data for the east/west streets; the remaining lines show the north/south streets. The format should be clear from the example.

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

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

Output

* Lines 1..?: Each line contains a direction letter and a number of blocks to travel in that direction.
每行有一个表示方向的字母和一个表示要开几个十字路口的数字表示.

Sample Input

3 6
+-+-+.+-+-+
|...|.....|
+-+.+-+-+-+
..|.......|
S-+-+-+.E-+

Sample Output

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


直接bfs,然后记录路径就行了……

#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;

struct na{
    int x,y;
};
const int fx[4]={0,1,0,-1},fy[4]={1,0,-1,0};
int n,m;
char map[81][81];
int cm[81][81];
char c;
queue <na> q;
void pri(int x,int y){
    int k,p;
    for(;;){
        k=cm[x][y];p=0;
        if (k==0) printf("E ");else
        if (k==1) printf("S ");else
        if (k==2) printf("W ");else
        printf("N ");
        while(cm[x][y]==k){
            x+=fx[k];
            y+=fy[k];
            if (map[x][y]=='+') p++;
        }
        if (map[x][y]=='E'){
            printf("%d",p+1);
            return;
        }
        printf("%d
",p);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    n=n*2-1;m=m*2-1;
    for (int i=0;i<n;i++)
    for (int j=0;j<m;j++){
        c=getchar();
        while(c=='
') c=getchar();
        map[i][j]=c;
        if (c=='E'){
            na tmp;
            tmp.x=i;tmp.y=j;
            q.push(tmp);
        }
        cm[i][j]=-1;
    }
    while(!q.empty()){
        na k=q.front();q.pop();
        for (int i=0;i<4;i++){
            na now=k;
            now.x+=fx[i];now.y+=fy[i];
            if (now.x<0||now.y<0||now.x>=n||now.y>=m) continue;
            if (map[now.x][now.y]=='.') continue;
            if (cm[now.x][now.y]==-1){
                cm[now.x][now.y]=i>1?i-2:i+2;
                if (map[now.x][now.y]=='S'){
                    pri(now.x,now.y);
                    return 0;
                }
                q.push(now);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/Enceladus/p/5040198.html