题目背景

长期的宅男生活中,JYY又挖掘出了一款RPG游戏。在这个游戏中JYY会

扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽。

题目描述

在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。当然了,一般来说,相比普通攻击,法术攻击会消耗更多的体力值(但由于游戏系统bug,并不保证这一点)。

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

输入输出格式

输入格式:
第一行包含一个整数N。

接下来N行,每行描述一个怪兽的信息;

其中第i行包含若干个整数,前三个整数为Si,Ki和Ri,表示对于i号怪兽,普通攻击需要消耗Si的体力,法术攻击需要消耗Ki的体力,同时i号怪兽死亡后会产生Ri个新的怪兽。表示一个新出现的怪兽编号。同一编号的怪兽可以出现多个。

输出格式:
输出一行一个整数,表示最少需要的体力值。

这道题去年十一小长假考过,当时一脸懵逼不会做,
考虑打怪兽的方式,如果我打的怪兽是只打的,那他分裂后成为的小怪兽一定是小的(这是最优情况下的必然),所以我们按照怪兽的法术抗性加入小根堆中,用一种既像拓扑又像最短路的东西去维护它。
具体做法为:建一张图连向打死后生成的怪兽,在建一张反图,每次取出堆顶后,扫描反边,将反边的入度减去,若如度为0,则扫描正边,看看是否可以更新原来的dp值,若成功更新,则把更新过后的点加入堆。
这样做为什么是对的呢(其实我也不知道)。
显然到最后我们肯定是要用法术攻击的,如果底层的法术攻击代价比上面的点代价还要大,那肯定不是最优解,我们肯定不去取,所以当一个点被更新的条件时当且仅当它的儿子的代价都要比他小时。
下面的话是我这篇题解的参考,并不是我写的。
有种解法是spfa,将法术攻击每个怪兽的体力值当做初始的路径长度,之后优化一个dis之后,将其推进队列,再更新其他怪兽。
如果按照打死每种怪兽的最小体力给怪兽排序的话,可知,假如一个耗体力大的怪兽是被普通攻击了,那么其变成的怪兽一定排在它前面(体力值比他小)。换言之,按照所耗体力值从小到大枚举每个怪兽,由当前枚举过的怪兽更新没有被枚举怪兽的体力值,再找到没有被枚举的怪兽中体力值最小的怪兽继续枚举,枚举的顺序一定是按照打死每种怪兽的最小体力递增排序的,当前体力值也是最小体力值。
每次拿出堆顶,更新刚好达到条件的点(条件即为该点所有出边指向的点都已出堆),如果更优则推入堆中,重复这个过程。
发现暴力判断条件的话时间复杂度显然不对,我们可以用拓扑的思想,建一张反图,每出堆一个点就将其连向的点入度-1,直至入度为0的时候更新该点。
时间复杂度O(nlogn+m)

下面贴代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define N 200009
using namespace std;
int n,r[N],x,tot,head[N],head1[N],tot1;
long long d[N],k[N];
bool vis[N];
struct w
{
int n,to;
}an[],an1[];
inline void add1(int u,int v)
{
an1[++tot1].n=head1[u];
an1[tot1].to=v;
head1[u]=tot1;
}
inline void add(int u,int v)
{
an[++tot].n=head[u];
an[tot].to=v;
head[u]=tot;
}
struct ha
{
long long val;
int pos;
};
bool operator < (ha a,ha b)
{
return a.val>b.val;
}
priority_queue<ha>q;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i)
{
scanf("%lld%lld%d",&d[i],&k[i],&r[i]);
for(int j=;j<=r[i];++j)
{
scanf("%d",&x);
add(x,i);
add1(i,x);
}
if(!r[i])k[i]=min(k[i],d[i]);
q.push(ha{k[i],i});
}
while(!q.empty())
{
ha u=q.top();q.pop();
if(k[u.pos]<u.val)continue;
if(vis[u.pos])continue;
vis[u.pos]=;
for(int i=head[u.pos];i;i=an[i].n)
{
int v=an[i].to;
r[v]--;
if(r[v]<=&&!vis[v])
{
long long ss=d[v];
for(int j=head1[v];j;j=an1[j].n)
ss+=k[an1[j].to];
if(k[v]>ss)
{
k[v]=ss;
q.push(ha{k[v],v});
}
}
}
}
cout<<k[];
}

JSOI2014骑士游戏(最短路)的更多相关文章

  1. 【BZOJ3875】[Ahoi2014&Jsoi2014]骑士游戏 SPFA优化DP

    [BZOJ3875][Ahoi2014&Jsoi2014]骑士游戏 Description  [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会扮演一个英勇的 ...

  2. p4042 [AHOI2014/JSOI2014]骑士游戏

    传送门 分析 我们发现对于一个怪物要不然用魔法代价使其无需考虑后续点要么用普通攻击使其转移到他所连的所有点上且所有边大于0 所以我们可以先将一个点的最优代价设为魔法攻击的代价 之后我们倒着跑spfa求 ...

  3. [BZOJ] 3875: [Ahoi2014&Jsoi2014]骑士游戏

    设\(f[x]\)为彻底杀死\(x\)号怪兽的代价 有转移方程 \[ f[x]=min\{k[x],s[x]+\sum f[v]\} \] 其中\(v\)是\(x\)通过普通攻击分裂出的小怪兽 这个东 ...

  4. 洛谷 P4042 [AHOI2014/JSOI2014]骑士游戏

    题意 有\(n\)个怪物,可以消耗\(k\)的代价消灭一个怪物或者消耗\(s\)的代价将它变成另外一个或多个新的怪物,求消灭怪物$的最小代价 思路 \(DP\)+最短路 这几天做的第一道自己能\(yy ...

  5. 2019.01.22 bzoj3875: [Ahoi2014&Jsoi2014]骑士游戏(spfa+dp)

    传送门 题意简述:nnn个怪物,对于编号为iii的怪物可以选择用aia_iai​代价将其分裂成另外的bib_ibi​个怪物或者用cic_ici​代价直接消灭它,现在问消灭编号为1的怪物用的最小代价. ...

  6. BZOJ3875 AHOI2014/JSOI2014骑士游戏(动态规划)

    容易想到设f[i]为杀死i号怪物所消耗的最小体力值,由后继节点更新.然而这显然是有后效性的,正常的dp没法做. 虽然spfa已经死了,但确实还是挺有意思的.只需要用spfa来更新dp值就可以了.dij ...

  7. bzoj 3875: [Ahoi2014&Jsoi2014]骑士游戏【dp+spfa】

    设f[i]为杀死i的最小代价,显然\( f[i]=min(k[i],s[i]+\sum f[to]) \) 但是这个东西有后效性,所以我们使用spfa来做,具体就是每更新一个f[i],就把能被它更新的 ...

  8. BZOJ3875: [Ahoi2014&Jsoi2014]骑士游戏

    [传送门:BZOJ3875] 简要题意: 给出n种怪物,每种怪物都带有三个值,S[i],K[i],R[i],分别表示对他使用普通攻击的花费,使用魔法攻击的花费,对他使用普通攻击后生成的其他怪物. 每种 ...

  9. LUOGU P4042 [AHOI2014/JSOI2014]骑士游戏 (spfa+dp)

    传送门 解题思路 首先设\(f[x]\)表示消灭\(x\)的最小花费,那么转移方程就是 \(f[x]=min(f[x],\sum f[son[x]] +s[x])\),如果这个转移是一个有向无环图,那 ...

随机推荐

  1. Java Map 集合实现类

    Map 用于保存具有映射关系的数据,集合里会保存两组值,一组用于保存Map里的key,一组用于保存Map里的value,key与map可以是任何引用类型数据.Map的key不允许重复.key与valu ...

  2. Java中有关Null的9件事(转)

    对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认 ...

  3. hadoop分布式系统架构详解

    hadoop 简单来说就是用 java写的分布式 ,处理大数据的框架,主要思想是 “分组合并” 思想. 分组:比如 有一个大型数据,那么他就会将这个数据按照算法分成多份,每份存储在 从属主机上,并且在 ...

  4. python之路--MRO和C3算法

    一 . MRO(method resolution order) 多继承的一种方法,一种查找的顺序 在python3 里面是一种新类式MRO 需要用都的是C3算法 class A: pass clas ...

  5. 协程和异步io

    一. 并发.并行.同步.异步.阻塞.非阻塞 1.并发:是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机(CPU)上运行,但任一个时刻点上只有一个程序在处理机上运 ...

  6. 重写TreeView模板来实现数据分层展示(二)

    前面一片文章实现TreeView的基本的模板重写,那么照着这个思路,我们再来写一个稍稍复杂的TreeView ,其它的内容都和前面系列内容相似,还是和之前文章介绍的一样,首先看看做出的DEMO的最终样 ...

  7. Chrome 75 & lazy-loading

    Chrome 75 & lazy-loading https://addyosmani.com/blog/lazy-loading/ https://chromestatus.com/feat ...

  8. 和docket的第一次亲密接触

    很久很久以前,第一次听说docker时,感觉很高大上,同时自我感觉会很难.所以一直没有详细了解.前一段时间偶尔看到关于docker的详细介绍,于是乎来了兴趣.自已折腾了一下,发现不是想象中的那么难. ...

  9. 利用 ajax自定义Form表单的提交方式

    需求场景:有时候单纯的form表单无法向后端传递额外的参数 比如需要action传递js异步生成的参数 ,form表单默认的action就无法满足需求,这时就需要我们自定义form表单的提交方式. h ...

  10. SSH整合Maven教程

    http://www.cnblogs.com/xdp-gacl/p/4239501.html