数据结构——最大值最小化 (划分子序列)
2014-10-31 23:44
211 查看
第一次写博客,就把第一篇文章给今天在sicily上刷的--最大值最小化
先上题:
把一个包含n个正整数的序列划分成m个连续的子序列(每个正整数恰好属于一个序列)。设第i个序列的各数之和为S(i),如何让所有S(i)的最大值尽量小?
例如序列1 2 3 2 5 4,划分成3个序列的最优方案为1 2 3 | 2 5 | 4,其中S(1)=6, S(2)=7, S(3)=4,最大值为7;如果划分成1 2 | 3 2 | 5 4,则最大值为9,不如刚才的好。
n≤106,所有数之和不超过109。
Input
There may be multiple cases.
The first line of the input gives two integer n and m. The next line contains n integers.
Output
For each case, output the minimum value.
Sample Input
Copy sample input to clipboard
6 3
1 2 3 2 5 4
Sample Output
7
先上题:
把一个包含n个正整数的序列划分成m个连续的子序列(每个正整数恰好属于一个序列)。设第i个序列的各数之和为S(i),如何让所有S(i)的最大值尽量小?
例如序列1 2 3 2 5 4,划分成3个序列的最优方案为1 2 3 | 2 5 | 4,其中S(1)=6, S(2)=7, S(3)=4,最大值为7;如果划分成1 2 | 3 2 | 5 4,则最大值为9,不如刚才的好。
n≤106,所有数之和不超过109。
Input
There may be multiple cases.
The first line of the input gives two integer n and m. The next line contains n integers.
Output
For each case, output the minimum value.
Sample Input
Copy sample input to clipboard
6 3
1 2 3 2 5 4
Sample Output
7
//目标学会用猜数字(二分)的方法,换个角度来解决问题 /*我们用二分查找的办法,查找范围是[数组的最大值(max),数组的和(sum)], * 在这个范围里面的元素x(二分查找用mid表示), * 能否使m个连续子序列所有的s(i)均不超过x,则该命题成立的最小的x即为答案。 * 该命题不难判断,只需贪心,每次尽量从左向右尽量多划分元素即可。 * (我们把该问题转化为递归分治问题,类似于二分查找。) * 首先取Sum和元素最大值的中值x, * 如果命题(judge)为假(就是说当子序列的最大值为x不能把数组分成m段),那么答案比x大; * 如果命题(judge)为真(就是说当子序列的最大值为x能把数组分成m段),则答案小于等于x。 * 问题得解,复杂度为O(n*logSum) */ #include <iostream> using namespace std; int array[2000000]; int b_search(int a[], int low, int high, int n, int m);// bool judge(int a[], int mid, int n, int m);//是否能把序列划分为每个序列之和不大于mid的m个子序列 int main() { int n; while (cin >> n) { int m; cin >> m; int sum = 0, max = -1; for (int i = 0; i < n; i++) { cin >> array[i]; sum += array[i]; if (array[i] > max) max = array[i]; } cout << b_search(array, max, sum, n, m) << endl; } return 0; } int b_search(int a[], int low, int high, int n, int m) { while (low < high) { int mid = (low + high) / 2; if (judge(a, mid, n, m)) {//能把序列划分为每个序列之和不大于mid的m个子序列, high = mid; //为求子序列最大值最小化,范围缩小为[low,mid], } else { //不能把序列划分为每个序列之和不大于mid的m个子序列 low = mid + 1;//为求子序列最大值最小化,范围缩小为[mid+1,high] } } return low; //此时low==high } bool judge(int a[], int mid, int n, int m) { //每次往右划分,划分完后,所用的划分线不大于m-1个即可 ,用k记录划分的段落数 int sum = 0, k = 0; for (int i = 0; i < n; i++) { sum += a[i]; if (sum > mid) {//当子序列的和超过假定的最大值mid时,划分 k++; //增加一条划分线 sum = a[i]; //sum从划分线的下一个元素开始计算 } } if (k < m) //(当子序列的最大值为mid时,可以实现划分)实际划分线<=m-1 return true; else //mid太小了,不能划分 return false; }
相关文章推荐
- 【数据结构与算法】最大子序列和问题的求解
- 数据结构——最大子序列和
- 【数据结构与算法】最大子序列
- 【数据结构与算法】小于等于k的最大连续子序列和
- 求最大连续子序列之和的线性算法 c# 数据结构
- 序列划分-使其最大值最小化
- 数据结构之一(引论及最大子序列和问题)
- 数据结构与算法——给定整数A1,A2,....An,....(可能有负数),求该数据序列的最大子序列的和
- 序列划分-使其最大值最小化
- 求最大子序列问题-数据结构
- 内存区划分;内存分配;堆、栈概念分析;动态内存管理数据结构及程序样例;
- 数据结构——算法之(018)( 和为n连续正数序列)
- 数据结构——最大堆和最小堆(C语言)
- 数据结构——算法之(025)( 求一个数组的最长递减子序列)
- 数据结构——算法之(020)( 和为n连续正数序列)
- 数据结构(C#)--二叉查找树的先序,中序,后序的遍历问题以及最大值,最小值,插入,删除
- 经典数据结构之最大堆
- 数据结构之(动态规划)之最长公共序列
- 数据结构实验之求二叉树后序遍历和层次遍历【由前序序列和中序序列求后序序列,二叉树的层次遍历】
- python-数据结构(列表,元组,字典,序列,引用)