ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【AHOI2014/JSOI2014】骑士游戏

2019-10-23 22:03:56  阅读:304  来源: 互联网

标签:怪兽 JSOI2014 int AHOI2014 vis spfa 杀死 骑士 普通攻击


JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击

两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死
怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽
而采用法术攻击则可以彻底将一个怪兽杀死

游戏世界中一共有N种不同的怪兽,分别由1到N编号
在1号怪兽入侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢

这真的是一道好题啊……
一开始想的是,使用普通攻击杀死一个怪物,产生了分裂体\(a_1\)~\(a_x\)
那么\(ans[i]=min(f[i]+ans[a1]+...+ans[an],g[i])\)
乱写的式子,就是说杀死其本体分裂体的最小价值与直接杀死本体的价值取min

但是这样一直递归下去求解的话……好像没有初始位置来着?
分裂关系可能成环,那dp就废了

打开题解看一眼仔细思索后发现居然要用spfa建模?

类比于跳楼机那道题,这个dp方程像spfa的松弛操作

那么类似的,我们搞个最短路来玩?

不过发现,并不能保证从一个定点开始跑出来的答案是最优的,所以初始化的时候要把所有节点入队

但现在仍然不能保证这样可以搞出正确答案啊?
毕竟这个队列的顺序并没有正确性
所以一旦更新了答案,就把当前点的父节点再次入队,看它的儿子是否有更优的解

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 600005
using namespace std;

int n,u,v,k,x;
int a[N];
ll dis[N];

struct Edge
{
    int next,to;
}edge[N<<1],edge2[N<<1];
int cnt=0,head[N],cnt2=0,head2[N];

inline void add_edge(int from,int to)
{
    edge[++cnt].next=head[from];
    edge[cnt].to=to;
    head[from]=cnt;
}

inline void add_edge2(int from,int to)
{
    edge2[++cnt2].next=head2[from];
    edge2[cnt2].to=to;
    head2[from]=cnt2;
}

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

queue<int> q;
bool vis[N];
void spfa()
{
    for(register int i=1;i<=n;++i) q.push(i),vis[i]=1;
    while(!q.empty())
    {
        int u=q.front();q.pop();vis[u]=0;
        ll res=a[u];
        for(register int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            res+=dis[v];
        }
        if(dis[u]>res)
        {
            dis[u]=res;
            for(register int i=head2[u];i;i=edge2[i].next)
            {
                int v=edge2[i].to;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}

int main()
{
    read(n);
    for(register int i=1;i<=n;++i)
    {
        read(a[i]);
        read(dis[i]);
        read(k);
        while(k--)
        {
            read(x);
            add_edge(i,x);
            add_edge2(x,i);
        }
    }
    spfa();
    printf("%lld\n",dis[1]);
    return 0;
}

标签:怪兽,JSOI2014,int,AHOI2014,vis,spfa,杀死,骑士,普通攻击
来源: https://www.cnblogs.com/tqr06/p/11729243.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有