题意:
给你一个长度为n的整型数组a,和一个整型x。你可以在数组a中的任意多个位置加x,然后取出a中的连续一段使得数值总和最大,问你位置数从0~n答案一次是多少?
题解:
又咕了一段时间…真舒服啊(不是)
首先看到5e3当然想的就是暴力,但是发现暴力的话,要找左右端点,然后又要考虑数量,很容易就上
N
3
N^3
N3,然后不知道为什么就想到了DP。那么
dp[i][j]表示位置i作为取的末尾,j个位置加x的时候的答案是多少。那么状态转移方程就是:
dp[i][j]=max(dp[i-1][j]+a[i],dp[i-1][j-1]+a[i]+x);
同时要注意记录答案:
ans[i]表示i个位置加x的时候的最大答案:
ans[j]=max(ans[j],dp[i][j]);
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int a[N],dp[N][N],ans[N];
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,x;
scanf("%d%d",&n,&x);
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dp[i][j]=0;
for(int i=1;i<=n;i++){
dp[i][0]=max(0,max(a[i],dp[i-1][0]+a[i]));
ans[0]=max(ans[0],dp[i][0]);
for(int j=1;j<=i;j++){
dp[i][j]=max(dp[i-1][j]+a[i],dp[i-1][j-1]+a[i]+x);
ans[j]=max(ans[j],dp[i][j]);
}
}
for(int i=0;i<=n;i++)
printf("%d ",ans[i]),ans[i+1]=max(ans[i+1],ans[i]);
printf("\n");
}
return 0;
}