最小m子段和(動態規划)


問題描述: 

給定n個整數組成的序列,現在要求將序列分割為m段,每段子序列中的數在原序列中連續排列。如何分割才能使這m段子序列的和的最大值達到最小?

輸入格式:

第一行給出n,m,表示有n個數分成m段,隨后一行給出n個數,以空格分隔

輸入樣例:

9 3

9 8 7 6 5 4 3 2 1

輸出樣例:

17

解釋:

9 8 | 7 6 | 5 4 3 2 1,9個數分成3段所有情況里這種分法的最大子段和(17)最小。

思路:

動態規划的一種模板,包括矩陣連乘,石子歸並等問題。先是考慮分的段數,然后考慮起點/終點,最后是每段中分割點的位置。

本題中使用 dp[i][j]表示前i個數分成j段里最小的最大子段和,則dp[i][j]=min{dp[i][1]-dp[k][1],dp[k][j-1] (1<=k<i)};

代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 99
 4 #define inf 0x3f3f3f3f
 5 int a[N],dp[N][N];//dp[i][j]表示前i個數分j段所有情況里最大子段和最小的
 6 int main()
 7 {
 8     int n,m;
 9     cin>>n>>m;
10     for(int i=1; i<=n; i++)
11         cin>>a[i];
12     for(int i=1; i<=n; i++)
13         dp[i][1]=dp[i-1][1]+a[i];
14     for(int r=2; r<=m; r++){
15         for(int i=1; i<=n; i++){
16             int mins=inf;
17             for(int k=1; k<i; k++){
18                 int t=max(dp[i][1]-dp[k][1],dp[k][r-1]);
19                 if(t<mins)  mins=t;
20             }
21             dp[i][r]=mins;
22         }
23     }
24     cout<<dp[n][m];
25     return 0;
26 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM