1. 程式人生 > >BZOJ 3875: [Ahoi2014]騎士遊戲

BZOJ 3875: [Ahoi2014]騎士遊戲

string bsp std 系統 ++ script n) 父節點 ron

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 題解:這題還是很巧妙的,首先對於這道題我們第一眼當然是DP了,當然設dp[i]表示殺死第i號怪物的最小費用,顯然殺死他的最小費用是用魔法費用殺死他的最小費用和用普攻殺死他和殺死其兒子們的最小費之和取min,當然這個dp是有後效性的,因為你殺死你這個怪之後顯然他有可能產生自己,所以我們可以用spfa解決這個問題,先把最小費設成魔法攻擊,然後每更是一次答案,就要把父節點一起放入隊列,這樣就可以去更新被當前節點更新的節點了。 代碼:
#include<iostream>
#include
<stdio.h> #include<stdlib.h> #include<algorithm> #include<queue> #include<vector> #include<cstring> #define ll long long const int MAXN=200010; using namespace std; ll pu[MAXN],mo[MAXN],n,num=0,tot=0,dp[MAXN],have[MAXN]; vector<ll> shang[MAXN];queue<ll>q; struct
edge{ int first; int next; int to; }a[10*MAXN]; void addedge(int from,int to){ a[++num].to=to; a[num].next=a[from].first; a[from].first=num; } void cl(){ memset(pu,0,sizeof(pu)); memset(dp,37,sizeof(dp)); } void spfa(){ for(int i=1;i<=n;i++){ have[i]=1;q.push(i);dp[i]=mo[i]; } while(!q.empty()){ ll now=q.front(),sum=pu[now],len; q.pop(); have[now]=0; for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; sum+=dp[to]; } if(dp[now]>sum){ dp[now]=sum,len=shang[now].size(); for(int i=0;i<len;i++){ if(!have[shang[now][i]]){ have[shang[now][i]]=1; q.push(shang[now][i]); } } } } } int main(){ cl(); scanf("%d",&n); for(ll i=1;i<=n;i++){ ll x,y,z; scanf("%lld%lld%lld",&x,&y,&z); pu[i]=x,mo[i]=y; for(ll j=1;j<=z;j++){ ll k;scanf("%lld",&k); addedge(i,k); shang[k].push_back(i); } } spfa(); printf("%lld",dp[1]); }

BZOJ 3875: [Ahoi2014]騎士遊戲