欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

牛客网【每日一题】7月29日题目精讲—Max Power

程序员文章站 2022-07-13 18:02:56
...

来源:牛客网:

Max Power

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

小卤蛋刚把dnf的技能点重新洗了一遍,现在他要重新加点,假设他的技能树一共有n层,第i层有n-i+1个
技能,每个技能只能够学习一次。除了第1层的技能可以直接学习外,其他技能学习都要学习前置技能,
即你要学习第i(i>=2)层第j列的技能,那么你要先学习第i-1层的第j列和第j+1列的技能。每个技能学习 后都会获得一定的战力加成。
现在小卤蛋有m个技能点,一个技能点可以学习一个技能,他想知道加完点后他可以获得的最大战力加成为多少。

输入描述:
有多组样例输入,输入到文件结束.
每组样例第一行输入2个整数n(1<=n<=50)和m(1<=m<=1300),对应题目上的含义。
接下来共有n行,第i行有n-i+1个数,代表这个技能学习后获得的战力加成(战力加成<=1000)。
输出描述:
输出最大的战力加成。
示例1
输入
复制

4 3
1 4 1 9
2 3 5
6 1
66

输出
复制

15

题解:

我们可以看出这是个倒三角的形状。要学技能x,就要学习它上面的两个技能,这两个技能上面的三个技能,一直推到第一层,这就是一个倒三角形状,也就是倒三角的内容我没必须全部学习。
我们从列的方向看,会发现每一列所学的技能是一个从上往下的一个连续区间,(中间若有断开则最底下的技能将无法学习)。其次,左一列总比右一列多学一个(如下)
所以我们就从右向左一列一列的转移
dp[i][j][k]表示前i列一共选了k个技能学习,第i列选了连续的前j个
dp[i][j][k]=max(dp[i-1][p][k-j]+sum[i][j])
保证倒三角内技能全部学习
其中:
sum[i][j]是列的前缀和,表示第i列前j个数字的和
p>=j-1,从j-1枚举到n-i+1枚举,
即第i-1列最少只比第i列少选一个(最多则可以选完)。
最后每个位置的dp[i][j][m]最大值为答案
牛客网【每日一题】7月29日题目精讲—Max Power

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=55;
int sum[maxn][maxn];
int dp[maxn][maxn][1308];
int a[maxn];
int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		for(int i=1;i<=n;i++)
		{
			a[i]=a[i-1]+i;
			for(int j=1;j<=n-i+1;j++)
			{
				int x;
				cin>>x;
				sum[i][j]=x+sum[i-1][j];
			}
		}
		memset(dp,0,sizeof(dp));
		int sun=0;
		for(int i=n;i;i--)
		{
			for(int j=0;j<=n-i+1;j++)
			{
				for(int k=a[j];k<=m;k++)
				{
					for(int p=max(j-1,0);p<n-i+1;p++)
					{
						dp[i][j][k] = max(dp[i][j][k], dp[i + 1][p][k - j] + sum[j][i]);
					}
					sun = max(sun, dp[i][j][m]);
				}
				
			}
			
		}
		cout<<sun<<endl;
	}
}