【模擬試題】技能樹 樹形DP

題目描述

  玩過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;
}
相關文章
相關標籤/搜索