【模拟试题】技能树 树形DP

来源:互联网 发布:最全p2p网络理财产品 编辑:程序博客网 时间:2024/05/19 00:42

题目描述

  玩过Diablo的人对技能树一定是很熟悉的。一颗技能树的每个结点都是一项技能,要学会这项技能则需要耗费一定的技能点数。只有学会了某一项技能以后,才能继续学习它的后继技能。每项技能又有着不同的级别,级别越高效果越好,而技能的升级也是需要耗费技能点数的。有个玩家积攒了一定的技能点数,他想尽可能地利用这些技能点数来达到最好的效果。因此他给所有的级别都打上了分,他认为效果越好的分数也越高。现在他要你帮忙寻找一个分配技能点数的方案,使得分数总和最高。

数据范围

很小很小qwq

样例输入

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

样例输出

42

解题思路

我觉得应该叫“技能森林”吧,为什么要叫技能树。。
要把森林树转换为二叉树,然后枚举分配左子树和右子树所用的技能点数。求最大值。

代码

#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;}
0 0
原创粉丝点击