1. 程式人生 > >bzoj3875 [Ahoi2014]騎士遊戲

bzoj3875 [Ahoi2014]騎士遊戲

str continue 一個 sta tac pop efi register 騎士遊戲

Description

【故事背景】 長期的宅男生活中,JYY又挖掘出了一款RPG遊戲。在這個遊戲中JYY會扮演一個英勇的騎士,用他手中的長劍去殺死入侵村莊的怪獸。 【問題描述】 在這個遊戲中,JYY一共有兩種攻擊方式,一種是普通攻擊,一種是法術攻擊。兩種攻擊方式都會消耗JYY一些體力。采用普通攻擊進攻怪獸並不能把怪獸徹底殺死,怪獸的屍體可以變出其他一些新的怪獸,註意一個怪獸可能經過若幹次普通攻擊後變回一個或更多同樣的怪獸;而采用法術攻擊則可以徹底將一個怪獸殺死。當然了,一般來說,相比普通攻擊,法術攻擊會消耗更多的體力值(但由於遊戲系統bug,並不保證這一點)。 遊戲世界中一共有N種不同的怪獸,分別由1到N編號,現在1號怪獸入侵村莊了,JYY想知道,最少花費多少體力值才能將所有村莊中的怪獸全部殺死呢?

Input

第一行包含一個整數N。 接下來N行,每行描述一個怪獸的信息; 其中第i行包含若幹個整數,前三個整數為Si,Ki和Ri,表示對於i號怪獸, 普通攻擊需要消耗Si的體力,法術攻擊需要消耗Ki的體力,同時i號怪獸死亡後會產生Ri個新的怪獸。表示一個新出現的怪獸編號。同一編號的怪獸可以出現多個。

Output

輸出一行一個整數,表示最少需要的體力值。

Sample Input

4
4 27 3 2 3 2
3 5 1 2
1 13 2 4 2
5 6 1 2

Sample Output

26

HINT

【樣例說明】 首先用消耗4點體力用普通攻擊,然後出現的怪獸編號是2,2和3。花費10點體力用法術攻擊殺死兩個編號為2的怪獸。剩下3號怪獸花費1點體力進行普通攻擊。此時村莊裏的怪獸編號是2和4。最後花費11點體力用法術攻擊將這兩只怪獸徹底殺死。一共花費的體力是4+5+5+1+5+6=26。 【數據範圍】 2<=N<=2*10^5,1<=Ri,Sigma(Ri)<=10^6,1<=Ki,Si<=5*10^14

正解:$spfa$。

碰到這種有後效性的$dp$一般可以用$spfa$解決。

我們只要按照$spfa$的思路,如果當前點被更新了,就用它去松弛別的點。

這樣按照最短路的思想來更新,是肯定可以獲得最優解的。

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8
#include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define sz (2000010) 14 #define N (200010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 vector <int> g1[N],g2[N]; 23 queue <int> Q; 24 25 ll s[N],k[N],f[N]; 26 int vis[N],n; 27 28 il ll gi(){ 29 RG ll x=0,q=1; RG char ch=getchar(); 30 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 31 if (ch==-) q=-1,ch=getchar(); 32 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 33 return q*x; 34 } 35 36 il void work(){ 37 n=gi(); 38 for (RG int i=1,r;i<=n;++i){ 39 s[i]=gi(),k[i]=gi(),r=gi(); 40 for (RG int j=1,x;j<=r;++j) 41 x=gi(),g1[i].push_back(x),g2[x].push_back(i); 42 } 43 for (RG int i=1;i<=n;++i) Q.push(i),vis[i]=1,f[i]=k[i]; 44 while (!Q.empty()){ 45 RG int x=Q.front(); Q.pop(); RG ll sum=s[x]; vis[x]=0; 46 for (RG int i=0;i<g1[x].size();++i) sum+=f[g1[x][i]]; 47 if (f[x]<=sum) continue; f[x]=sum; 48 for (RG int i=0,v;i<g2[x].size();++i){ 49 v=g2[x][i]; 50 if (!vis[v]) Q.push(v),vis[v]=1; 51 } 52 } 53 printf("%lld\n",f[1]); return; 54 } 55 56 int main(){ 57 File("knight"); 58 work(); 59 return 0; 60 }

bzoj3875 [Ahoi2014]騎士遊戲