给你一个整数数组,返回它的某个 非空 子数组(连续元素)在执行一次可选的删除操作后,所能得到的最大元素总和。
换句话说,你可以从原数组中选出一个子数组,并可以决定要不要从中删除一个元素(只能删一次哦),(删除后)子数组中至少应当有一个元素,然后该子数组(剩下)的元素总和是所有子数组之中最大的。
注意,删除一个元素后,子数组 不能为空。
首先对题目进行分析可以把题目进行简单的拆解就首先不删除时求出最大字数组中的和
写出动态规划方程
DP[I] = MAX(A[I],DP[I-1]+A[[I]);
代码入下
#include #include
#include using namespace std;
typedef long long ll; ll a[100100];
int main() {
memset(dp1,0,sizeof(0));
int n,i,j; scanf("%d",&n);
ll MAX=-999999999; for(i=0;i<n;i++)
{ scanf("%lld",&a[i]);
MAX=max(MAX,a[i]); }
dp1[0]=a[0]; for(i=1;i<n;i++)
{ dp1[i]=max(dp1[i-1]+a[i],a[i]);
}
for(i=1;i<n-1;i++) {
MAX=max(dp1[i],MAX); }
MAX=max(MAX,dp1[n-1]);
printf("%lld",MAX); return 0;
} 然后从左到右进行遍历在从右向左进行遍历,即可下面是对一个样例进行的分析
{ memset(dp1,0,sizeof(0));
memset(dp2,0,sizeof(0)); int n,i,j; scanf("%d",&n); ll MAX=-999999999;
for(i=0;i<n;i++) { scanf("%lld",&a[i]); MAX=max(MAX,a[i]);
} dp1[0]=a[0]; dp2[n-1]=a[n-1]; for(i=1;i<n;i++)
{ dp1[i]=max(dp1[i-1]+a[i],a[i]); } /for(i=n-2;i>=0;i–)
{ dp2[i]=max(dp2[i+1]+a[i],a[i]); } for(i=0;i<n;i++)
{ printf("%lld “,dp1[i]); } printf(”\n");
for(i=0;i<n;i++) { printf("%lld ",dp2[i]); }
return 0;/ for(i=1;i<n-1;i++) { MAX=max(dp1[i],MAX);
MAX=max(dp2[i],MAX); MAX=max(dp1[i-1]+dp2[i+1],MAX); } MAX=max(MAX,dp1[n-1]);
MAX=max(MAX,dp2[0]); printf("%lld",MAX); return 0;
} 还有另外一个解法
先给出动态方程 // dp[i][0] 表示i节点没有删除过节点的最大值
// dp[i][1] 表示i节点删除过过节点的最大值
// 递归公式// dp[i][0] = max( arr[i], dp[i-1][0] + arr[i]) #没删除过的,是arr[i]或者 dp[i-1][0]+arr[i] 取大值
// dp[i][1]=max(dp[i-1][0],dp[i-1][1]+arr[i]) #删除过的dp[i-1]加上本身 和 没有删除过的p[i-1]删除dp[i] 取大值nt maximumSum(int* arr, int arrSize){
int result = arr[0]; int dp[100000][2];
dp[0][0] = arr[0]; for(int i=1;i<arrSize;i++)
{ if(dp[i-1][0]<= 0)
dp[i][0] = arr[i]; else
dp[i][0] = dp[i-1][0]+arr[i];
if(dp[i-1][0] > dp[i-1][1]+arr[i]) dp[i][1] = dp[i-1][0];
else dp[i][1] = dp[i-1][1]+arr[i];
if(dp[i][1]<arr[i]) dp[i][1] = arr[i];
if(result<dp[i][1]) result = dp[i][1];
} return result;
}