1007 Maximum Subsequence Sum(两种思路)

Posted CSU迦叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1007 Maximum Subsequence Sum(两种思路)相关的知识,希望对你有一定的参考价值。

1.解法1 思路

对于动态规划来说,最关键的就是找到状态转移方程,本题设置一个前向数组,元素predp[i]表示的是以元素i结尾的连续数列和的最大值,转移方程是predp[i] = max(predp[i-1]+a[i],a[i])。要做的事就是完成这个dp数组,然后找到最大的dp[i]。

根据i可以直接得到结束元素,那开始元素怎么办呢?我们还需要另开一个计数数组n[maxn],记录下数目。

注意:要获得坐标尽可能小的起始元素和终止元素,体现在代码的两个地方

1是:哪怕前面的元素加上是鸡肋,为了起始坐标小,也把它加上

for(int i=1;i<n;i++){
	if(predp[i-1]+a[i]>=a[i]){
		num[i] = num[i-1]+1;
		predp[i] = predp[i-1]+a[i];
	}else{
		num[i] = 1;
		predp[i] = a[i];	
	}
}

 2是:在挑选最大dp[i]的时候,哪怕后面出现了同样大的,也不要

int preI,preMax = -1;
for(int i=0;i<n;i++){
	if(predp[i]>preMax){
		preMax = predp[i];
		preI = i;
	}
}

2.解法2 思路

设置一前一后两个状态转移方程,并且由于最后希望起始坐标和终止坐标都尽可能小,所以对于前向数组找最大下标的时候,必须是大于,才能允许坐标被增大,对于反向数组找最大下标的时候,满足大于等于,就允许坐标被减小。原理是:正向得到最大值的数列,和反向得到最大值的数列是同一个。

3.解法1 AC代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;

const int INF = 1000000000;//10的9次方 
const int maxn = 100010;
const double eps = 1e-3;

int n;
int a[maxn];
int predp[maxn];
int num[maxn];
bool isSpe = true;

int main(){
	
	
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		if(a[i]>=0)isSpe = false;//说明不是特例 
	}
	
	if(isSpe){
		printf("0 %d %d\\n",a[0],a[n-1]);
		return 0;
	}
	
	//解决predp[0]和num[0]
	predp[0] = a[0];
	num[0] = 1;
	
	for(int i=1;i<n;i++){
		if(predp[i-1]+a[i]>=a[i]){
			num[i] = num[i-1]+1;
			predp[i] = predp[i-1]+a[i];
		}else{
			num[i] = 1;
			predp[i] = a[i];	
		}
	}
	
	int preI,preMax = -1;
	for(int i=0;i<n;i++){
		if(predp[i]>preMax){
			preMax = predp[i];
			preI = i;
		}
	}
	
	
	
	printf("%d %d %d\\n",preMax,a[preI-num[preI]+1],a[preI]);	
	
	
	return 0; 
}

4.解法2 非满分(22/25)代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;

const int INF = 1000000000;//10的9次方 
const int maxn = 100010;
const double eps = 1e-3;

int n;
int a[maxn];
int predp[maxn];
int postdp[maxn];
bool isSpe = true;

int main(){
	
	
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		if(a[i]>=0)isSpe = false;//说明不是特例 
	}
	
	if(isSpe){
		printf("0 %d %d\\n",a[0],a[n-1]);
		return 0;
	}
	
	predp[0] = max(0,a[0]);
	for(int i=1;i<n;i++){
		predp[i] = max(predp[i-1]+a[i],a[i]);
	}
	int preI,preMax = -1;
	for(int i=0;i<n;i++){
		if(predp[i]>preMax){
			preMax = predp[i];
			preI = i;
		}
	}
	
	postdp[n-1] = max(0,a[n-1]);
	for(int i=n-2;i>=0;i--){
		postdp[i] = max(postdp[i+1]+a[i],a[i]);
	}
	int postI,postMax = -1;
	for(int i=n-1;i>=0;i--){
		if(postdp[i]>=postMax){
			postMax = postdp[i];
			postI = i;
		}
	}
	
	printf("%d %d %d\\n",postMax,a[postI],a[preI]);	
	
	
	return 0; 
}

以上是关于1007 Maximum Subsequence Sum(两种思路)的主要内容,如果未能解决你的问题,请参考以下文章