[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];
}

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

时间: 2024-10-17 20:12:28

[SCU 4498] RunningPhoton's Nightmare (BFS预处理+SPFA)的相关文章

HDU 3533 Escape(BFS+预处理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3533 题目大意:给你一张n* m的地图,人在起点在(0,0)要到达终点(n,m)有k(k<=100)座炮台,每座炮台都有各自的发射方向.发射周期和发射速度,每隔一段时间会发射一定速度的炮弹,人每秒可以选择停在原地或者往上下左右走,问是否能在时间d之内安全到达终点.如果可以,请输出最短时间. 解题思路:BFS+预处理,分为以下几点: ①预处理,用step[x][y][t]记录(x,y)在时间t是否被炮

poj_3669_Meteor Shower(BFS+预处理)

http://poj.org/problem?id=3669 /*思路:BFS+预处理 先预处理会爆炸的区域,BFS,遇到-1则结束*/ #include <iostream> #include <queue> #include <algorithm> using namespace std; int visit[1001][1001]; int dx[5] = {0,0,1,0,-1}; int dy[5] = {0,1,0,-1,0}; typedef struct

poj3026Borg Maze(bfs预处理+最小生成树)

题目链接: 啊哈哈,点我点我 思路: 首先把图中的A S预处理出来,然后对这些点逐一做bfs找到这些点到其它点的最短路径,然后建图完毕也用最小生成树的prim算法或者kruscal算法求出连接所有点的最短距离..不知道为嘛用dis数组去维护为什么会超时,而在结构体里面用step数组却可以过,我也不知道为什么,纠结了很多天..我把错误的代码贴出来,希望各位帮我找出原因,不胜感激... 题目: Borg Maze Time Limit: 1000MS   Memory Limit: 65536K T

【2016 ICPC亚洲区域赛北京站 E】What a Ridiculous Election(BFS预处理)

Description In country Light Tower, a presidential election is going on. There are two candidates,  Mr. X1 and Mr. X2, and both of them are not like good persons. One is called a liar and the other is called a maniac. They tear(Chinese English word,

hdu 1072 Nightmare BFS,第一次刷BFS的题,感好牛逼的。。。

Nightmare Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7758    Accepted Submission(s): 3723 Problem Description Ignatius had a nightmare last night. He found himself in a labyrinth with a ti

cdoj 1380 Xiper的奇妙历险(2) [八数码问题 bfs + 预处理]

快要NOIP 2016 了,现在已经停课集训了.计划用10天来复习以前学习过的所有内容.首先就是搜索. 八数码是一道很经典的搜索题,普通的bfs就可求出.为了优化效率,我曾经用过康托展开来优化空间,甚至还用过A*来优化时间.不过这道题懒得写了,就一个普普通通的bfs,再加上一个stl 的map就水过了. 首先题目要求有多达10000组数据,依次搜索肯定是不行的,我试过用A*来写,第2组数据就会T掉,所以我们考虑用一个预处理.从末尾状态搜索所有可行的状态,并用一个map来存储答案.然后就很好写了.

HDU 3567 Eight II BFS预处理

题意:就是八数码问题,给你开始的串和结束的串,问你从开始到结束的最短且最小的变换序列是什么 分析:我们可以预处理打表,这里的这个题可以和HDU1430魔板那个题采取一样的做法 预处理打表,因为八数码问题实际上是每个小块位置的变化,上面的数字只是用来标记位置的, 所以通过映射将初末序列进行置换就好了,然后因为每次的x字符的置换位置不一样 所以需要以123456789这个初始串打9遍表就好了733ms #include <iostream> #include <cstdio> #inc

POJ 3669 Meteor Shower (BFS + 预处理)

Meteor Shower Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9677   Accepted: 2718 Description Bessie hears that an extraordinary meteor shower is coming; reports say that these meteors will crash into earth and destroy anything they hi

【搜索】 HDU 3533 Escape BFS 预处理

要从0,0 点 跑到m,n点  路上会有k个堡垒发射子弹,有子弹的地方不能走,子弹打到别的堡垒就会消失,或者一直飞出边界(人不能经过堡垒 可以上下左右或者站着不动 每步都需要消耗能量  一共有eng个能量 先预处理出地图 用三维数组表示mp[x][y][time] time表示该时间的地图上储存不能走的点 然后就是普通BFS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <s