树形动规_(技能树)
技能樹(SGOI)
skill.pas/c/cpp
【問題描述】
玩過 Diablo 的人對技能樹一定是很熟悉的。一顆技能樹的每個結點都是一項技能,要學會這項技能則需
要耗費一定的技能點數。只有在學會了某一項技能以后,才能繼續學習它的后繼技能。每項技能又有著不同的級
別,級別越高效果越好,而技能的升級也是需要耗費技能點數的。
有個玩家積攢了一定的技能點數,他想盡可能地利用這些技能點數來達到最好的效果,因此他給所有技能的
所有級別都打上了分,他認為效果越好的則分數越高。現在他要你幫忙尋找一個分配技能點數的方案,使得分數
總和最高。
【輸入格式】
第一行是一個整數 n(1<=n<=20),表示所有不同技能的總數。接下來依次給出了這 n 個不同技能的詳細
描述。每個技能描述共包括 5 行,第一行是該技能的名稱,第二行是該技能在技能樹中的父技能的名稱,為空
則表示該技能不需要任何的先修技能便能學習。第三行是一個整數 L(1<=L<=20) ,表示這項技能所擁有的最
高等級。第四行共有 L 個整數,其中第 i 個整數表示把這項技能從第 i-1 級升到第 i 級所需要的技能點數(0
級表示沒有學習過)。第五行也包括了 L 個整數,其中第 i個整數表示該玩家對這項技能的第 i 級的效果評分,
分數不超過 20。在技能描述之后是玩家所用角色的描述,共有兩行。第一行是一個整數 P(0<=P<=100),表
示目前所擁有的技能點數。接下來一行是 n 個整數,依次表示角色當前所習得的技能級別,0 表示尚未學習。這里
不會出現非法的情況,譬如在沒有學習某項技能的時候已經習得了它的后繼技能。
【輸出格式】
只需包括一個整數 S,表示你的技能點最佳分配方案所得到的分數總和。
【輸入樣例】
3
Freezing Arrow
Ice Arrow
3
3 3 3
15 4 6
Ice Arrow
Cold Arrow
2
4 3
10 17
Cold Arrow
?
3
3 3 2
15 5 2
10
0 0 1
【輸出樣例】
42
【時間限制】
1s
【空間限制】
64M
//------------------------------------------------------------------------------------------------
分析:樹形動規,多叉樹轉二叉樹.
f[i,j]表示以i為根的子樹,花j點技能點,能得到的最大分數.
枚舉給左右兒子分配的點數進行轉移,記憶化搜索.
code:
type skill=recordn,f:string;l:longint;v,p:array[0..21] of longint; end; const maxn=21;maxp=101; var s:array[0..maxn] of skill;f:array[0..maxn,0..maxp] of longint;learn,l,r:array[0..maxn] of longint;n,i,j,fa,tmp,p,ans:longint;function find(st:string):longint;var o:longint;beginfor o:=1 to n doif s[o].n=st then exit(o);exit(0);end;function maxx(a,b:longint):longint;beginif a>b then exit(a); exit(b);end;function DP(t,m:longint):longint;var max,now,o,cost,value,q:longint;beginif f[t,m]>=0 then exit(f[t,m]);max:=DP(r[t],m); //不學這種技能if learn[t]>0 then //已經學過的話,向下接著學for o:=1 to m dobeginnow:=DP(l[t],o)+DP(r[t],m-o);max:=maxx(max,now);end;cost:=0;value:=0;for o:=learn[t]+1 to s[t].l do //把這個技能接著學下去begincost:=cost+s[t].v[o];value:=value+s[t].p[o];for q:=0 to m-cost dobeginnow:=DP(l[t],q)+DP(r[t],m-cost-q)+value;max:=maxx(max,now);end;end;f[t,m]:=max;exit(max);end;beginassign(input,'skill.in'); reset(input);assign(output,'skill.out'); rewrite(output);readln(n);for i:=1 to n dobeginreadln(s[i].n);readln(s[i].f);readln(s[i].l);for j:=1 to s[i].l do read(s[i].v[j]);readln;for j:=1 to s[i].l do read(s[i].p[j]);readln;end;readln(P);for i:=1 to n do read(learn[i]);for i:=1 to n dobeginfa:=find(s[i].f);if l[fa]=0 then l[fa]:=ielsebegintmp:=l[fa];while r[tmp]<>0 do tmp:=r[tmp];r[tmp]:=i;end;end;fillchar(f,sizeof(f),255);for i:=0 to maxp do f[0,i]:=0;ans:=DP(l[0],P);writeln(ans);close(input);close(output); end.轉載于:https://www.cnblogs.com/exponent/archive/2011/08/06/2129483.html
總結
以上是生活随笔為你收集整理的树形动规_(技能树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1649元起 华为畅享50 Pro开卖:
- 下一篇: DM、EV两条腿越走越快!比亚迪7月新能