3-11 最小m段和问题
问题描述
给定n个整数组成的序列,现在要求将序列分割为m段,每段子序列中的数在原序列中连续排列。如何分割才能使这m段子序列的和的最大值达到最小?
编程计算该序列的最优m段分割,使m段子序列的和的最大值达到最小。
数据输入:
第1行中有 2个正整数n和m(0 <= m <= n <= 200)。正整数n是序列的长度;正整数m是分割的段数。 接下来的一行中有n个整数。
Java
import java.util.Scanner;
public class ZuiXiaoMDuanHe {
private static int[] numbers;
private static int[][] f;
private static int MAX = 100000;
/*
f[i][j] 将前i个数分成j段的最小最大值
f[i][1] 前i个数的和
当j>1时,假设前k个数分为j-1段,从k+1~i为第j段,则有:
f[k][j-1] 前k个数分为j-1段的最小最大值
f[i][1]-f[k][1] 前i个数减去前k个数分成一段,即为 从k+1~i的第j段
可见,f[i][j] = min{max{f[i][1]-f[k][1],f[k][j-1]}}
*/
/*
input data:
9 3
9 8 7 6 5 4 3 2 1
*/
public static void main(String[] args){
int n, m;
Scanner input = new Scanner(System.in);
while (true){
n = input.nextInt();
m = input.nextInt();
if(n<m || n==0){
System.out.println(0);
return;
}
numbers = new int[n+1];
f = new int[n+1][m+1];
for(int i=1; i<=n; i++)
numbers[i] = input.nextInt();
solve(n, m);
System.out.println(f[n][m]);
}
}
private static void solve(int n, int m){
int i,j,k,temp,maxt;
for(i=1; i<=n; i++)
f[i][1] = f[i-1][1] + numbers[i];
for(j=2; j<=m; j++)
for(i=j; i<=n; i++){
for(k=1,temp=MAX; k<i; k++){
maxt = max(f[i][1]-f[k][1], f[k][j-1]);
if(temp > maxt)
temp = maxt;
}
f[i][j] = temp;
}
}
private static int max(int a, int b){
return a > b ? a : b;
}
}
Input & Output
1 1
10
10
9 3
9 8 7 6 5 4 3 2 1
17
Reference
王晓东《计算机算法设计与分析》(第3版)P92

本文探讨如何将一个整数序列分割成m段,使得这m段子序列的和最大值达到最小。通过问题描述和Java代码实现,展示了动态规划在解决此类问题中的应用。

被折叠的 条评论
为什么被折叠?



