暑假集训中期测试 Problem H: 跳跳 (最短路)

Description

 一个每块地板标记着0~9某个数字的迷宫,其中标记1的地板不可以走,标记2~9的地板可以不花时间地跳到任意相同数字的位置,也可以和标记0的地板一样向前后左右任意方向花1个单位时间移动1的距离。给出起点和终点,求起点到终点的最短时间。

Input

 每组数据第一行一个n,表示尺寸,2 <= n <= 100。

接下来n行每行n个0~9的字符,或S表示起点,E表示终点,S和E的运动规则与0相同。整个地图只有一个S和一个E。

Output

 每组数据输出一个数,占一行,表示起点到终点可以花费的最短时间。

如果无法到达重点,输出"Oh No!"

Sample Input

5
0S100
00131
00300
00000
003E0
3
S12
010
10E

Sample Output

4
Oh No!
 
分析:这题表面上是BFS的题,实质上是最短路的题,用到了spfa的思想。
View Code
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define N 101

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};

struct node
{
    int x,y;
};

int n;
int t[N][N],inq[N][N];
char map[N][N];
int px[10][N*N],py[10][N*N];
int cnt[10];
int sx,sy,ex,ey;
void spfa()
{
    queue<node> q;
    int x,y,nx,ny;
    int ans;
    node cur,next;
    bool f[10];
    bool success=false;

    memset(f,0,sizeof(f));
    memset(t,-1,sizeof(t));
    memset(inq,0,sizeof(inq));

    cur.x=sx;
    cur.y=sy;
    t[sx][sy]=0;

    q.push(cur);
    inq[sx][sy]=1;
    while(!q.empty() && !success)
    {
        cur=q.front(),q.pop();
        x=cur.x;
        y=cur.y;
        inq[x][y]=0;
        if(x==ex && y==ey)
        {
            success=true;
            ans=t[x][y];
        }
        for(int i=0;!success && i<4;i++)
        {
            nx=x+dx[i];
            ny=y+dy[i];
            if(nx<0 || ny<0 || nx>=n || ny>=n || map[nx][ny]=='1')  continue;
            next.x=nx;
            next.y=ny;
            if(map[nx][ny]>='2' && map[nx][ny]<='9' && !f[map[nx][ny]-'0'])
            {
                int k=map[nx][ny]-'0';
                f[k]=true;
                for(int i=0;i<cnt[k];i++)
                {
                    nx=px[k][i];
                    ny=py[k][i];
                    next.x=px[k][i];
                    next.y=py[k][i];
                    t[nx][ny]=t[x][y]+1;
                    inq[nx][ny]=1;
                    q.push(next);
                }
            }
            else if(t[nx][ny]==-1 || t[nx][ny]>t[x][y]+1)
            {
                t[nx][ny]=t[x][y]+1;
                if(!inq[nx][ny])
                {
                    inq[nx][ny]=1;
                    q.push(next);
                }
            }
        }
    }
    if(success) printf("%d\n",ans);
    else    puts("Oh No!");
}
int main()
{
    int i,j,k;
    while(~scanf("%d",&n))
    {
        memset(cnt,0,sizeof(cnt));
        for(i=0;i<n;i++)
        {
            scanf("%s",map[i]);
            for(j=0;j<n;j++)
            {
                if(map[i][j]=='S')  sx=i,sy=j;
                if(map[i][j]=='E')  ex=i,ey=j;
                if(map[i][j]>='2' && map[i][j]<='9')
                {
                    k=map[i][j]-'0';
                    px[k][cnt[k]]=i;
                    py[k][cnt[k]++]=j;
                }
            }
        }
        spfa();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/algorithms/p/2615670.html