数组分段和最大值最小问题
2013-05-06 18:18
232 查看
原文地址:/article/7173884.html
1. 题目:给定一个数组,和一个值k,数组分成k段。要求这k段子段和最大值最小。求出这个值。
2.分析:这道题目很经典,也很难,个人认为很难。文章中给出了三种算法:算法1,暴力搜索。本题暴力搜索算法并不是很明显,可以使用递归实现暴力搜索。递归首先要有递归式:
n n-1
M[n, k] = min { max { M[j, k-1], ∑ Ai } }
j=1 i=j
n表示数组长度,k表示数组分成几段。初始化条件:
[/code]
1. 题目:给定一个数组,和一个值k,数组分成k段。要求这k段子段和最大值最小。求出这个值。
2.分析:这道题目很经典,也很难,个人认为很难。文章中给出了三种算法:算法1,暴力搜索。本题暴力搜索算法并不是很明显,可以使用递归实现暴力搜索。递归首先要有递归式:
n n-1
M[n, k] = min { max { M[j, k-1], ∑ Ai } }
j=1 i=j
n表示数组长度,k表示数组分成几段。初始化条件:
M[1, k] = A0
n-1 M[n, 1] = ∑ Ai
i=0
View Code #include <iostream> #include <cassert> using namespace std; int sum(int A[], int from, int to) { int total = 0; for (int i = from; i <= to; i++) total += A[i]; return total; } //递归的暴力搜素算法 //指数时间的复杂度 int partition(int A[], int n, int k) { if (k == 1) return sum(A, 0, n-1); if (n == 1) return A[0]; int best = INT_MAX; for (int j = 1; j <= n; j++) best = min(best, max(partition(A, j, k-1), sum(A, j, n-1))); return best; } //改进的动态规划算法 //时间复杂度:O(kN2) //空间复杂度:O(kN) const int MAX_N = 100; int findMax(int A[], int n, int k) { int M[MAX_N+1][MAX_N+1] = {0}; int cum[MAX_N+1] = {0}; for (int i = 1; i <= n; i++) cum[i] = cum[i-1] + A[i-1]; for (int i = 1; i <= n; i++) M[i][1] = cum[i]; for (int i = 1; i <= k; i++) M[1][i] = A[0]; for (int i = 2; i <= k; i++) { for (int j = 2; j <= n; j++) { int best = INT_MAX; for (int p = 1; p <= j; p++) { best = min(best, max(M[p][i-1], cum[j]-cum[p])); } M[j][i] = best; } } return M [k]; } int getMax(int A[], int n) { int max = INT_MIN; for (int i = 0; i < n; i++) { if (A[i] > max) max = A[i]; } return max; } int getSum(int A[], int n) { int total = 0; for (int i = 0; i < n; i++) total += A[i]; return total; } int getRequiredPainters(int A[], int n, int maxLengthPerPainter) { int total = 0, numPainters = 1; for (int i = 0; i < n; i++) { total += A[i]; if (total > maxLengthPerPainter) { total = A[i]; numPainters++; } } return numPainters; } //想不到的二分查找算法 //时间复杂度:O(N log ( ∑ Ai )). //空间复杂度:0(1) int BinarySearch(int A[], int n, int k) { int lo = getMax(A, n); int hi = getSum(A, n); while (lo < hi) { int mid = lo + (hi-lo)/2; int requiredPainters = getRequiredPainters(A, n, mid); if (requiredPainters <= k) hi = mid; else lo = mid+1; } return lo; } int main() { enum{length=9}; int k=3; int a[length]={9,4,5,12,3,5,8,11,0}; cout<<partition(a,length,k)<<endl; cout<<findMax(a,length,k)<<endl; cout<<BinarySearch(a,length,k)<<endl; return 0; }
[/code]
相关文章推荐
- 数组分段和最大值最小问题
- 数组分段和最大值最小问题
- 数组分段和最大值最小问题
- 数组中的最大值以及最小值的位置变换的问题(C++)
- 数组中的最大值以及最小值的位置变换的问题(C++)
- 关于求数组的最大值和最小值问题(C代码)
- 求数组的最大值 最小值问题 -Math方法
- 编程之美寻找数组中的最大值和最小值以及扩展问题
- 在数组中限制次数的取最大值和最小值问题
- 编程之美2.10寻找数组中的最大值和最小值扩展问题Java版
- 用递归法求解一个数组中的最大值和最小值的问题
- Java常识求阶层!的和 ,获取某个数组中的最小值,定义数组,获得成绩之和,平均成绩,最小成绩,最大成绩。等问题大全
- 动态规划经典问题03:数组中最大的数对差(或最小的数对差)
- 如何求出数组中最小(或者最大)的k个数(least k问题)
- 最大子数组和问题的解
- js 取数组最大值、最小值.
- JavaScript中有关一个数组中最大值和最小值及它们的下表的输出的解决办法
- 从数组中获取最大或最小值的解释
- 编程之美——寻找数组中的最大值和最小值
- 最大子数组问题