暑假集训中期测试 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;

}

 

你可能感兴趣的:(最短路)