題目地址: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開成一維數組,再開一個Max數組(Max[i][j]表示前j個數將會分成i(可能是分成i-1或者i-2或者....i-i+1)個區間後的最大區間和,但是這裏開二維的話還是會出現超時和數組太大的問題,所以這裏也用一維數組,具體操作方法,請看代碼)。既然知道了解決方法那麼給出新的狀態轉移方程:
如果這題用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;
}
注意初始化!!!