基礎DP (1) Max Sum Plus Plus(動態規劃+m子段和的最大值)

題目地址:https://vjudge.net/contest/295210#problem

參考博客:https://blog.csdn.net/codeswarrior/article/details/80310401

題目大意:輸入m,n,和a[i](1<=i<=n),在a數組中找m個不重疊的區間,且區間和最大。

方法:dp.

        用dp[i][j]來前j個數分成i個區間的後所有區間和,所以會出現兩種情況:a[j]+dp[i][j-1] (即a[j]不新開一個區間,而存入前一個區間中去),或者a[j]自己新開一個區間a[i]+dp[i-1][k](即將a[j]存入);狀態轉移方程:

                         dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][k])+a[j]) (k<j)

但是,這個方法會出現兩個問題:查詢超時,數組太大。

       在原來的基礎下進行改進。dp開成一維數組,再開一個Max數組(Max[i][j]表示前j個數將會分成i(可能是分成i-1或者i-2或者....i-i+1)個區間後的最大區間和,但是這裏開二維的話還是會出現超時和數組太大的問題,所以這裏也用一維數組,具體操作方法,請看代碼)。既然知道了解決方法那麼給出新的狀態轉移方程:

                        dp[j]=max(dp[j-1]+a[j],Max[j-1]+a[j])

如果這題用c++寫的話,用int來表示就行了,如果非要用long long ,最好加個ios::sync_with_stdio(false);

code:

/*
https://vjudge.net/contest/295210#problem/A
*/
#include<iostream>
#include<string.h>

using namespace std;

typedef long long ll;

const int inf=0x7fffffff;
const int maxn=1000005;

int dp[maxn],Max[maxn],a[maxn];

int main(){
//	ios::sync_with_stdio(false);
	int n,m;
	int i,j;
	int ma;
	while(cin>>m>>n){
		for(i=1;i<=n;i++) cin>>a[i];
		memset(dp,0,sizeof dp);
		memset(Max,0,sizeof Max);
		
		for(i=1;i<=m;i++){
			ma=-inf;
			for(j=i;j<=n;j++){//分成i個區間,至少需要i個數。
				dp[j]=max(dp[j-1]+a[j],Max[j-1]+a[j]);
				Max[j-1]=ma;
				ma=max(ma,dp[j]);
			}
		}
		
		cout<<ma<<endl;
	}
	return 0;
}

注意初始化!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章