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

[bzoj3875][Ahoi2014]騎士遊戲

cor pla cli name php out 用法 open none

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

Source

By 佚名上傳

dp轉移方程顯而易見,設f[i]為殺死i所需最小代價,則f[i]=min(K[i],s[i]+sigma(f[t])) (t為i所有兒子),但dp偏序灰常不明確

可以利用Super_Fast的玄學思想,一開始將每個點都放入隊列(相當於強制轉移),當一個點被更新時,將其所有父親放入隊列,更新它的父親。

還有一定不會重復更新環,因為有環的話f值只會越來越大

技術分享
 1 // It is made by XZZ
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 #define rep(a,b,c) for(rg int a=b;a<=c;a++)
 6 #define drep(a,b,c) for(rg int a=b;a>=c;a--)
 7 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
 8 #define il inline
 9 #define rg register
10 #define vd void
11 #define t (dis[i])
12 typedef long long ll;
13 il ll gi(){
14     rg ll x=0;rg char ch=getchar();
15     while(ch<0||ch>9)ch=getchar();
16     while(ch>=0&&ch<=9)x=x*10+ch-0,ch=getchar();
17     return x;
18 }
19 const int maxn=200010,maxm=1000001<<1;
20 int fir[maxn],dis[maxm],nxt[maxm],id=1;
21 il vd add(int a,int b,int first=1){
22     nxt[++id]=fir[a],fir[a]=id,dis[id]=b;
23     if(first)add(b,a,0);
24 }
25 ll s[maxn],k[maxn],f[maxn];
26 ll que[maxn],hd,tl;
27 bool inque[maxn];
28 int main(){
29     ll n=gi(),r;
30     rep(i,1,n){
31         s[i]=gi(),k[i]=f[i]=gi(),r=gi();
32     while(r--)add(i,gi());
33     }
34     hd=0,tl=n;
35     rep(i,1,n)que[i-1]=i,inque[i]=1;
36     while(hd^tl){
37     int now=que[hd];
38     ll res=s[now];
39     erep(i,now)if(i%2==0)res+=f[t];
40     if(res<f[now]){
41         f[now]=res;
42         erep(i,now)if(i%2&&!inque[t])
43             que[tl++]=t,inque[t]=1,tl%=maxn;
44     }
45     ++hd,hd%=maxn,inque[now]=0;
46     }
47     printf("%lld\n",f[1]);
48     return 0;
49 }
View Code

[bzoj3875][Ahoi2014]騎士遊戲