题意:
有一颗n层的技能树,第i层有n-i+1个技能,学习第i层第j个技能则必须先学习第i-1层第i和i+1个技能,第一层的技能可以直接学。你能学m个技能,求你最大的战力加成为多少?

思路:
dp
我们发现如果第i层第j个技能学习了,则以它为底的倒三角的技能一定学习了。
设dp[i][j][r]为第n列到第i列中学习了r个技能且第i列学习了前j个技能时的最大加成。
sum[i][j]为第j列前i行的和。
我们可以写出状态方程:
dp[i][j][r]=max(dp[i+1][p][r-j]+sum[j][i])(p>=j-1(满足学习前置技能条件))

代码:

#include <bits/stdc++.h>

typedef long long ll;

using namespace std;

const ll inf=1000000007;

int dp[55][55][1350], a[55][55], sum[55][55];

int main()
{
    int n, m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(sum,0,sizeof(sum));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n-i+1;j++)
            {
                scanf("%d",&a[i][j]);
                sum[i][j]=sum[i-1][j]+a[i][j];
            }
        }
        int ans=0;
        for(int i=n;i>=1;i--)
        {
            for(int j=0;j<=n-i+1;j++)
            {
                for(int r=j*(j+1)/2;r<=m;r++)
                {
                    for(int l=max(0,j-1);l<=n-i;l++)
                    {
                        dp[i][j][r]=max(dp[i][j][r],dp[i+1][l][r-j]+sum[j][i]);
                        if(r==m)
                        {
                            ans=max(ans,dp[i][j][r]);
                        }
                    }
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}