玩過Diablo的人對技能樹必定是很熟悉的。一顆技能樹的每一個結點都是一項技能,要學會這項技能則須要耗費必定的技能點數。只有學會了某一項技能之後,才能繼續學習它的後繼技能。每項技能又有着不一樣的級別,級別越高效果越好,而技能的升級也是須要耗費技能點數的。有個玩家積攢了必定的技能點數,他想盡量地利用這些技能點數來達到最好的效果。所以他給全部的級別都打上了分,他認爲效果越好的分數也越高。如今他要你幫忙尋找一個分配技能點數的方案,使得分數總和最高。 c++
很小很小qwqmarkdown
3
Freezing Arrow
Ice Arrow
3
3 3 3
15 4 6
Ice Arrow
Cold Arrow
2
4 3
10 17
Cold Arrow
None
3
3 3 2
15 5 2
10
0 0 1學習
42ui
我以爲應該叫「技能森林」吧,爲何要叫技能樹。。
要把森林樹轉換爲二叉樹,而後枚舉分配左子樹和右子樹所用的技能點數。求最大值。spa
#include <bits/stdc++.h>
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
inline string Getstr(){string ret="";char ch=getchar();while(!isalpha(ch))ch=getchar();while(ch!='\n')ret+=ch,ch=getchar();return ret;}
int L[25],vl[25][25],w[25][25],v[25][25],Now[25],n,p;
namespace Dp{
int son[25][2],tmp[25],fa[25],dp[25][6666],root=1;
void Init(){memset(dp,-1,sizeof(dp));memset(tmp,-1,sizeof(tmp));memset(son,0,sizeof(son));}
void Build(){
for(int i=1;i<=n;i++)
if(~tmp[fa[i]])
son[tmp[fa[i]]][1]=i,tmp[fa[i]]=i;
else
son[fa[i]][0]=i,tmp[fa[i]]=i;
}
int DP(int x,int vl){
if(!x)return 0;
if(~dp[x][vl])return dp[x][vl];
int Max=DP(son[x][1],vl);
if(Now[x])
for(int i=0;i<=vl;i++)
Max=max(Max,DP(son[x][0],i)+DP(son[x][1],vl-i));
int Sum1=0,Sum2=0;
for(int i=1;i<=L[x];i++){
if(i>Now[x])Sum1+=w[x][i],Sum2+=v[x][i];
for(int j=0;j<=vl-Sum1;j++)
Max=max(Max,DP(son[x][0],j)+DP(son[x][1],vl-Sum1-j)+Sum2);
}
return dp[x][vl]=Max;
}
}
string fa[25];
map<string,int>Map;
void Init(){
n=Getint();
for(int i=1;i<=n;i++){
Map[Getstr()]=i;
fa[i]=Getstr();
L[i]=Getint();
for(int j=1;j<=L[i];j++)w[i][j]=Getint();
for(int j=1;j<=L[i];j++)v[i][j]=Getint();
}
p=Getint();
for(int i=1;i<=n;i++)Now[i]=Getint();
for(int i=1;i<=n;i++){
if(Map[fa[i]])Dp::fa[i]=Map[fa[i]];
else Dp::fa[i]=0;
}
}
int main(){
Init();
Dp::Init();
Dp::Build();
cout<<Dp::DP(Dp::son[0][0],p)<<"\n";
return 0;
}