给你n排书,问拿m本书的最大价值。每一次拿只能从任意排书的最左端或者是最右端拿。
思路:
1、贪心显然容易GG,考虑DP。
2、然后考虑一个这样的问题:虽然局部最优不能带来整体最优,但是局部最优可以通过动态规划的方式来达到整体最优,我们不妨设w【i】【j】表示第i行拿j本书的最大价值,也就是我刚才所谓的局部最优,如果我们有了这个值,那么再设定dp【i】【j】表示从第一行开始规划规划到了第i行一共拿j本书的最大价值。
3、那么状态转移方程:
dp【i】【j】=max(dp【i】【j】,dp【i-1】【j-jj】+w【i】【jj】);
4、那么问题在考虑回来,w【i】【j】要如何求?其实并不难,我们求每一行的前缀和,以及后缀和即可。具体处理细节,看下边代码即可
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int dp[150][10050];
int qian[150][150];
int hou[150][150];
int w[150][150];
int a[150][150];
int k[150];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
memset(w,0,sizeof(w));
memset(dp,0,sizeof(dp));
memset(qian,0,sizeof(qian));
memset(hou,0,sizeof(hou));
for(int i=1;i<=n;i++)
{
scanf("%d",&k[i]);
for(int j=1;j<=k[i];j++)
{
scanf("%d",&a[i][j]);
qian[i][j]=qian[i][j-1]+a[i][j];
}
}
for(int i=1;i<=n;i++)
{
int tmpp=1;
for(int j=k[i];j>=1;j--)
{
hou[i][tmpp]=hou[i][tmpp-1]+a[i][j];
tmpp++;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k[i];j++)
{
w[i][j]=max(qian[i][j],hou[i][j]);
for(int l=1;l<=j;l++)
{
w[i][j]=max(qian[i][l]+hou[i][j-l],w[i][j]);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int jj=0;jj<=j&&jj<=k[i];jj++)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-jj]+w[i][jj]);
}
}
}
printf("%d\n",dp[n][m]);
}
}