[SCU 4498] RunningPhoton's Nightmare (BFS预处理+SPFA)

SCU - 4498

给定一张网格图,其中有一些不可到达点和一些时间重置装置
RunningPhoton从起点出发,身上有一个定时炸弹,当时间置0时他就会死
但是在置0前碰到时间重置装置又能重置时间
问 RunningPhoton是否能到达终点
若能,则输出最短时间,若不能,则输出 “Poor RunningPhoton”

这题虽然地图是有 600*600,但是有不超过 150个重置装置
普通 bfs搜的话肯定爆炸,因为你要存每个装置是否被用过了
正确解法如下:
因为我们只关心重置装置,起点,终点的位置
所以以每个重置装置及起点,终点作为起点都跑一次 bfs,
计算出两两间的最短距离后构一张图,将距离小于 K的连上边
最后再从起点跑一次 spfa即可

但是这题数据好像很水,用普通的 bfs也迷之能过

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) (a*a)

const int maxn=600+10,INF=0x3f3f3f3f;
const int dir[4][2]={0,1,0,-1,1,0,-1,0};
struct data
{
    int x,y,t;
    data(int tx,int ty,int tt):x(tx),y(ty),t(tt){}
};
struct Edge{int u,v,w,nxt;};

int N,M,K,ncnt;
char Map[maxn][maxn];
int vis[maxn][maxn];
int posi[200][2];
int edn,last[maxn];
Edge edge[152*152+10];
int dist[200];
bool inq[200];

void adde(int,int,int);
void init(int,int,int);
int spfa(int,int);

int main()
{
    int T;
    scanf("%d", &T);
    for(int ck=1; ck<=T; ck++)
    {
        edn=0;MST(last,-1);
        ncnt=0;
        int sx,sy,tx,ty;

        scanf("%d%d%d", &N, &M, &K);
        for(int i=1; i<=N; i++)
        {
            scanf(" %s", Map[i]+1);
            for(int j=1; j<=M; j++)
            {
                if(Map[i][j]=='R') {ncnt++;posi[ncnt][0]=i;posi[ncnt][1]=j;}
                if(Map[i][j]=='S') {sx=i;sy=j;}
                if(Map[i][j]=='E') {tx=i;ty=j;}
            }
        }
        ncnt++;
        posi[0][0]=sx; posi[0][1]=sy;
        posi[ncnt][0]=tx; posi[ncnt][1]=ty;
        for(int i=0; i<=ncnt; i++) init(i, posi[i][0], posi[i][1]);
// for(int i=0; i<=ncnt; i++) printf("%d: %d %d\n", i, posi[i][0], posi[i][1]);
// for(int i=0; i<edn; i++) printf("%d -> %d: %d\n", edge[i].u, edge[i].v, edge[i].w);

        int ans=spfa(0,ncnt);
        if(ans<INF) printf("%d\n", ans);
        else puts("Poor RunningPhoton!");
    }
    return 0;
}

void init(int np, int sx, int sy)
{
    MST(vis,0x3f);
    queue<data> que;
    que.push(data(sx, sy,0));
    vis[sx][sy]=0;

    while(que.size())
    {
        data &u=que.front();
        for(int d=0; d<4; d++)
        {
            int x=u.x+dir[d][0];
            int y=u.y+dir[d][1];
            if(x<=0||y<=0||x>N||y>M||u.t+1>=vis[x][y]||Map[x][y]=='W') continue;
            que.push(data(x,y,u.t+1));
            vis[x][y]=u.t+1;
        }
        que.pop();
    }
    for(int i=0; i<=ncnt; i++)
    {
        int x=posi[i][0], y=posi[i][1];
        if(i==np||vis[x][y]>=K) continue;
        adde(np,i,vis[x][y]);
    }
}

void adde(int u,int v,int w)
{
    edge[edn].u=u;
    edge[edn].v=v;
    edge[edn].w=w;
    edge[edn].nxt=last[u];
    last[u]=edn++;
}

int spfa(int S,int T)
{
    MST(dist,0x3f);
    CLR(inq);
    queue<int> que;
    que.push(S);
    dist[S]=0;
    inq[S]=1;

    while(que.size())
    {
        int u=que.front();
        for(int e=last[u]; ~e; e=edge[e].nxt)
        {
            int v=edge[e].v, w=edge[e].w;
            if(dist[v]>dist[u]+w)
            {
                dist[v]=dist[u]+w;
                if(!inq[v])
                {
                    que.push(v);
                    inq[v]=1;
                }
            }
        }
        inq[u]=0;
        que.pop();
    }
    return dist[T];
}

你可能感兴趣的:(bfs)