P3393 逃离僵尸岛

本文分享了使用Dijkstra算法解决“逃离僵尸岛”问题的编程经验,通过预处理危险城市,采用DFS和BFS算法判断城市状态,最终实现最短路径计算。

P3393 逃离僵尸岛

啊。好久不写dij手都生了

这道题就是预先处理出是否是危险城市,然后跑一个最短路就行了

然后因为我感觉这个对时间要求不大紧。判断危险城市时就写了个电风扇(DFS)

然后T飞了呜呜呜~~

//Dan数组是标记一个城市是否是危险城市
void danger(int now,int dist)
{
    if(dist>s)  return ;
    if(!Dan[now])   Dan[now]=1;
    if(!dist)   Dan[now]=-1;//-1表示感染城市
    for(int i=head[now];i;i=line[i].nxt)
        danger(line[i].p,dist+1);
}

然后又怒改了一波百分数(BFS)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using std::swap;
using std::queue;
const int N=101000,M=202000;
struct Data
{
    int p;
    long long dis;
    bool operator < (const Data &a)const 
    {
        return dis<a.dis;
    }
};
struct Link
{
    int p;
    int nxt;
};
Data base[M<<3];
Link line[M<<1];
int head[N],tail;
int n,m,k,s,p,q,len;
int zombie[N];
int Dan[N];
long long dis[N];
bool get[N];
Data top()
{
    return base[1];
}
void push(Data a)
{
    base[++len]=a;
    int pos=len;
    while((pos>>1)&&base[pos]<base[pos>>1])
    {
        swap(base[pos],base[pos>>1]);
        pos>>=1;
    }
    return ;
}
void pop()
{
    swap(base[1],base[len--]);
    int pos=1,nxt;
    while(true)
    {
        nxt=pos;
        if(base[pos<<1]<base[nxt]&&(pos<<1)<=len)
            nxt=pos<<1;
        if(base[pos<<1|1]<base[nxt]&&(pos<<1|1)<=len)
            nxt=pos<<1|1;
        if(pos==nxt)    break;
        swap(base[pos],base[nxt]);
        pos=nxt;
    }
    return ;
}
void add(int a,int b)
{
    line[++tail].p=b;
    line[tail].nxt=head[a];
    head[a]=tail;
}
queue<int>Q;
void danger()
{
    while(!Q.empty())
    {
        int pas=Q.front();Q.pop();
        for(int i=head[pas];i;i=line[i].nxt)
            if(!Dan[line[i].p]&&Dan[pas]<s)
            {
                Dan[line[i].p]=Dan[pas]+1;
                Q.push(line[i].p);
            }
    }
    for(int i=1;i<=k;i++)   Dan[zombie[i]]=-1;
}
int main()
{
    memset(dis,127,sizeof(dis));
    scanf("%d%d%d%d%d%d",&n,&m,&k,&s,&p,&q);
    for(int i=1;i<=k;i++)
    {
        scanf("%d",&zombie[i]); 
        Q.push(zombie[i]);
    }
    int a,b;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    danger();
    Data pas,nxt;pas.p=1;pas.dis=0;
    push(pas);
    while(len)
    {
        pas=top();
        while(get[pas.p]){ pop();pas=top(); }
        get[pas.p]=true;dis[pas.p]=pas.dis;
        if(pas.p==n)    break;
        for(int i=head[pas.p];i;i=line[i].nxt)
        {
            int v=line[i].p;
            long long dist=p;
            if(Dan[v]==-1)      continue;
            if(Dan[v])  dist=q;
            if(v==n)    dist=0;
            if(dis[pas.p]+dist<dis[v])
            {
                nxt.p=v;
                nxt.dis=dis[v]=dis[pas.p]+dist;
                push(nxt);
            }
        }
    }
    printf("%lld",dis[n]);
}

转载于:https://www.cnblogs.com/Lance1ot/p/9648908.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值