最大子段和部分問題(DP)

2021-07-04 09:46:01 字數 4320 閱讀 5409

1.

一維陣列求最大子段和;(hdu1003,hoj1760)

這就是最基礎的最大子段和模型:給出乙個序列a[0],a[1],a[2],...a[n],要求出連續的一段,使其總和最大.如果設dp[i]表示以第i個元素為結尾的最大總和,那麼顯然有:

dp[i] = dp[i - 1] + a[i] (dp[i - 1] > 0 時)

a[i] 

(dp[i - 1] < 0 時)

顯然這個模型空間複雜度可以壓縮至o(1),即:

dp += a[i] (dp > 0)

dp = a[i] (dp < 0)

//ac(含有最大和的起始位置和終止位置)

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include //基本輸入流

#include //基本輸出流

#include //基於字串的流

#include //stl 通用模板類

#include //複數處理

#include //浮點環境

#include //整數格式轉換

#include //布林環境

#include //整型環境

#include //通用型別數學巨集

#define l(a,b,c) for(int a = b;a >= c;a --)

#define m(a,b,c) for(int a = b;a <= c;a ++)

#define n(a,b) memset(a,b,sizeof(a));

const int max=1<<30;

const int min=-max;

using namespace std;

int dp[100011],a[100011];

int main()

if(max>0)

printf("the maximum winning streak is %d.\n",max);

else

printf("losing streak.\n");

}return 0;}

2.最大m子段和(hdu1024 , poj2479)

已知有n個數,求m段不相交的子段權值之和最大,

狀態轉移方程:dp[i][j]表示以i為結尾元素的j個子段的數和

dp[i][j]=max(dp[i-1][j]+a[i],dp[i-k][j-1]+a[i]);其中(j-1<=k<=n-m+1)

此題實現這種思想:

for(i=1;i<=m;i++)}}

//ac

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//#include //基本輸入流

//#include //基本輸出流

//#include //基於字串的流

//#include //stl 通用模板類

//#include //複數處理

//#include //浮點環境

//#include //整數格式轉換

//#include //布林環境

//#include //整型環境

//#include //通用型別數學巨集

#define l(a,b,c) for(int a = b;a >= c;a --)

#define m(a,b,c) for(int a = b;a <= c;a ++)

#define n(a,b) memset(a,b,sizeof(a));

#define maxx(a,b)   ((a)>(b)?a:b)

#define minn(a,b)   ((a)<(b)?a:b)

const int max=1<<30;

const int min=-max;

const int n=1001000;

using namespace std;

int a[n],pre[n],num[n];

int main()

}cout<

//ac

(用c++輸入超時)

#include

#include

#include

#include

#include

#include

#include

#include

#define l(a,b,c) for(int a = b;a >= c;a --)

#define m(a,b,c) for(int a = b;a <= c;a ++)

#define n(a,b) memset(a,b,sizeof(a));

#define maxx(a,b)   ((a)>(b)?a:b)

#define minn(a,b)   ((a)<(b)?a:b)

const int max=1<<30;

const int min=-max;

const int n=50005;

using namespace std;

int a[n],pre[n],num[n];

int main()

}cout< 3.

最大子矩陣和

所謂萬變不離其宗,這個的思路和上面是一樣的. 維數增加了一維,所以可以考慮把它轉化成一維的"基本問題". 我們可以先統計sum[i][j](以下假設下標從1開始) : 第i行,從開頭到第j個元素的總值,這樣, 第i行從第j個元素到第k個元素的總價值就是sum[i][k] - sum[i][j - 1]. 這個預處理的時間複雜度是o(n^2). 這時,這個問題就轉化成了一維的最大子段和問題了: 列舉每一行中,第i到第j個元素(1 <= i <= j <= n),就可以把j - i + 1個元素的總和看成乙個元素(轉化的過程), 然後,對n個這樣的元素求最大子段和即可. 這一部分的時間複雜度是o(n^3),因此總複雜度也為o(n^3).

//ac

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//#include //基本輸入流

//#include //基本輸出流

//#include //基於字串的流

//#include //stl 通用模板類

//#include //複數處理

//#include //浮點環境

//#include //整數格式轉換

//#include //布林環境

//#include //整型環境

//#include //通用型別數學巨集

#define l(a,b,c) for(int a = b;a >= c;a --)

#define m(a,b,c) for(int a = b;a <= c;a ++)

#define n(a,b) memset(a,b,sizeof(a));

#define maxx(a,b)   ((a)>(b)?a:b)

#define minn(a,b)   ((a)<(b)?a:b)

const int max=1<<30;

const int min=-max;

using namespace std;

int dp[111][111],a[111][111];

int main()

}int ans,max=min;

m(i,1,n)    //每一行的起始位置}}

cout<

4.最大子立方體

最大子段和 (dp

n個整數組成的序列a1,a2,a3,ann,求該序列如ai ai 1 aj的連續子段和的最大值。當所給的整數均為負數時和為0。例如 2,11,4,13,5,2,和最大的子段為 11,4,13。和為20。第1行 整數序列的長度n 2 n 50000 第2 n 1行 n個整數 10 9 ai 10 9 ...

dp 最大子段和

注意 在實際問題中可能題目要求至少選乙個,可能可以乙個都不選 只返回最大子段和 include include using namespace std const int maxn 2e5 10 const int inf 0x7fffffff int n int a maxn int maxsum...

最大子段和(dp)

最基礎的的最大子段和,設dp i dp i dp i 為以num i num i num i 結尾的最大子段和,有dp i m ax d p i 1 n um i nu m i dp i max dp i 1 num i num i dp i max dp i 1 num i n um i 最終結果...