JSOI2014骑士游戏(最短路)

时间:2022-09-12 20:42:47

题目背景

长期的宅男生活中,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】&lbrack;Ahoi2014&amp&semi;Jsoi2014&rsqb;骑士游戏 SPFA优化DP

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

  2. p4042 &lbrack;AHOI2014&sol;JSOI2014&rsqb;骑士游戏

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

  3. &lbrack;BZOJ&rsqb; 3875&colon; &lbrack;Ahoi2014&amp&semi;Jsoi2014&rsqb;骑士游戏

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

  4. 洛谷 P4042 &lbrack;AHOI2014&sol;JSOI2014&rsqb;骑士游戏

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

  5. 2019&period;01&period;22 bzoj3875&colon; &lbrack;Ahoi2014&Jsoi2014&rsqb;骑士游戏(spfa&plus;dp)

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

  6. BZOJ3875 AHOI2014&sol;JSOI2014骑士游戏(动态规划)

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

  7. bzoj 3875&colon; &lbrack;Ahoi2014&amp&semi;Jsoi2014&rsqb;骑士游戏【dp&plus;spfa】

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

  8. BZOJ3875&colon; &lbrack;Ahoi2014&amp&semi;Jsoi2014&rsqb;骑士游戏

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

  9. LUOGU P4042 &lbrack;AHOI2014&sol;JSOI2014&rsqb;骑士游戏 &lpar;spfa&plus;dp&rpar;

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

随机推荐

  1. java 执行 jar 包中的 main 方法

    java 执行 jar 包中的 main 方法 通过 OneJar 或 Maven 打包后 jar 文件,用命令: java -jar ****.jar执行后总是运行指定的主方法,如果 jar 中有多 ...

  2. 转:IT公司的十大内耗,别说你公司没有!

    这篇文章是以前看到的,觉得写得非常好,转载在自己BLOG作为记录.原文:http://www.pmtoo.com/news/2015/0108/7260.html. 当企业发展到一定时期时,会不可避免 ...

  3. DuckHunter Attacks

    DuckHunter Attacks   DuckHunter Attacks是从USB Rubber Ducky (USB橡皮鸭)发展过来的HID攻击方式.USB Rubber Ducky是从201 ...

  4. &lbrack;记录&rsqb;gulp compass

    因为个人习惯用compass,所以gulp中,还是用compass进行编译scss文件. 1. 使用npm安装gulp-compass npm install gulp-compass --save- ...

  5. AWS&lpar;0&rpar; - Amazon Web Services

    Computer EC2 – Virtual Servers in the Cloud EC2 Container Service – Run and Manage Docker Containers ...

  6. offsetLeft

    offsetLeft 获取的是相对于父对象的左边距,且返回值为数字: left 获取或设置相对于 具有定位属性(position定义为relative)的父对象 的左边距,且返回值是字符串eg:10p ...

  7. 20165309 实验四 Android程序设计

    2017-2018-2 20165309实验四<Java面向对象程序设计>实验报告 一.实验内容 1.Android Studio的安装测试 2.Activity测试 3.UI测试 4.布 ...

  8. Spark VS Presto VS Impala

    https://www.quora.com/What-is-the-difference-between-Spark-and-Presto

  9. 转换成json字符串&comma;与json字符串转换成java类型都要先转换成json对象

    转换成json字符串,与json字符串转换成java类型都要先转换成json对象

  10. 字典表&plus;委托替代switch解决思路

    参考:http://www.jianshu.com/p/8887b3b3e8ba 代码 namespace 解决Switch { class Program { delegate string fun ...