题目背景
长期的宅男生活中,JYY又挖掘出了一款RPG游戏。在这个游戏中JYY会
扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽。
题目描述
在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。当然了,一般来说,相比普通攻击,法术攻击会消耗更多的体力值(但由于游戏系统bug,并不保证这一点)。
游戏世界中一共有N种不同的怪兽,分别由1到N编号,现在1号怪兽入侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢?
输入格式
第一行包含一个整数N。
接下来N行,每行描述一个怪兽的信息;
其中第i行包含若干个整数,前三个整数为Si,Ki和Ri,表示对于i号怪兽,普通攻击需要消耗Si的体力,法术攻击需要消耗Ki的体力,同时i号怪兽死亡后会产生Ri个新的怪兽。表示一个新出现的怪兽编号。同一编号的怪兽可以出现多个。
输出格式
输出一行一个整数,表示最少需要的体力值。
输入输出样例
输入 #1复制
4
4 27 3 2 3 2
3 5 1 2
1 13 2 4 2
5 6 1 2
输出 #1复制
26
有点DP的感觉,但是有后效性,所以没办法DP。
对于一个怪物,很有可能是成环的。若A死后生成B,C。那么A可以像最短路的三角不等式一样,缩边。
我们直接对所有点跑SPFA,看是否可以松弛,然后如果可以松弛,那么连向他的点因为这次松弛之后,也是可能松弛的,所以我们重复在放进队列当中。
AC代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10,M=1e6+10;
int n,d[N],k[N],s[N],vis[N],res; queue<int> q;
int head[N],nex[M],to[M],tot;
vector<int> g[N];
inline void add(int a,int b){
to[++tot]=b; nex[tot]=head[a]; head[a]=tot; g[b].push_back(a);
}
void spfa(){
for(int i=1;i<=n;i++) q.push(i),d[i]=k[i],vis[i]=1;
while(q.size()){
int u=q.front(),sum=s[u]; q.pop(); vis[u]=0;
for(int i=head[u];i;i=nex[i]) sum+=d[to[i]];
if(sum>=d[u]) continue; d[u]=sum;
for(int i=0;i<g[u].size();i++){
if(!vis[g[u][i]]) q.push(g[u][i]),vis[g[u][i]]=1;
}
}
}
signed main(){
cin>>n;
for(int i=1,r,x;i<=n;i++){
scanf("%lld %lld %lld",&s[i],&k[i],&r);
while(r--) scanf("%lld",&x),add(i,x);
}
spfa();
cout<<d[1]<<endl;
return 0;
}
来源:CSDN
作者:青烟绕指柔!
链接:https://blog.csdn.net/weixin_43826249/article/details/103810881