LightOj 1076 - Get the Containers (折半枚举 绝世好题)

题目链接:

  http://www.lightoj.com/volume_showproblem.php?problem=1076

题目描述:

  给出n个数,要求分成m段,问这m段中最大的总和,最小是多少?

解题思路:

  二分每一段的长度,然后判定枚举长度是否合法。

  刚看到这个题目就想到了dp,但是dp的复杂度还是很高的,然后就一直放着,放着。。。。学了折半枚举,拿起来一看,哇塞,简直惊喜啊!

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7
 8 #define LL long long
 9 #define maxn 1010
10 #define mod 100000007
11
12 int n, m, a[maxn];
13 bool bin_srea (int key) //判断key是否合法,
14 {
15     int num = 0, tmp = 0;
16     for (int i=0; i<n; i++)
17     {
18         if (a[i] > key)
19             return false;
20         if (tmp + a[i] <= key)
21         {
22             tmp += a[i];
23         }
24         else
25         {
26             tmp = a[i];
27             num ++;
28         }
29     }
30     return num < m;
31 }
32
33 int main ()
34 {
35     int T, L = 0;
36     scanf ("%d", &T);
37
38     while (T --)
39     {
40         int l, r, ans;
41
42         l = r = 0;
43         scanf("%d %d", &n, &m);
44         for (int i=0; i<n; i++)
45         {
46             scanf ("%d", &a[i]);
47             r += a[i];
48             l = max (l, a[i]);
49         }
50
51         while (l <= r)  ///枚举每一段的长度
52         {
53             int mid = (l + r) / 2;
54             if (bin_srea(mid))
55             {
56                 ans = mid;
57                 r = mid - 1;
58             }
59             else
60                 l = mid + 1;
61         }
62
63         printf ("Case %d: %d\n", ++L, ans);
64     }
65     return 0;
66 }
时间: 2024-10-25 07:12:10

LightOj 1076 - Get the Containers (折半枚举 绝世好题)的相关文章

LightOJ 1076 Get the Containers 二分答案

1076 - Get the Containers PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB A conveyor belt has a number of vessels of different capacities each filled to brim with milk. The milk from conveyor belt is to be filled into 'm' c

LightOJ 1235 - Coin Change (IV) (折半枚举)

题目链接: http://www.lightoj.com/volume_showproblem.php?problem=1235 题目描述: 给出n个硬币,每种硬币最多使用两次,问能否组成K面值? 解题思路: 因为K草鸡大,尽管n很小,但是2^n很大,无法用背包做到O(nK)的复杂度.如果暴力枚举复杂度立马飙升到O(2^(n+1)).··········· 所以引进一种新的算法,折半查找:把所要枚举的值,先把前部分的值所有情况枚举出来,再把后部分的值所有情况枚举出来并排序,结合二分进行查找. 这

lightoj 1235 Coin Change (IV)(折半枚举)

话说这是俺们学校暑假集训完的一道题,刚看到以为是到水题,后来发现者复杂度也太大了,受不了了,比赛完也没搞出来,然后欣爷说这是折半枚举.然后就摸摸的学了一下,又把这道题写了一下, 所谓折半枚举就是先算出来一半,再算一半,然后用二分查找看看能不能搞到这一发状态,可以的话就是可以了, 题意:给你两个数n,k,下面再给你n个数,表示你现在有的硬币的面值,每种硬币面值的有两个,看是否可以支付k 题解思路:首先以为只有三种状态,直接dfs就好了,后来发现复杂度太大了,然后死了撸就是上面的,详细情残考代码 源

Load Balancing 折半枚举大法好啊

Load Balancing 给出每个学生的学分.   将学生按学分分成四组,使得sigma (sumi-n/4)最小.         算法:   折半枚举 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <

CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。

1514: Packs Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 61  Solved: 4[Submit][Status][Web Board] Description Give you n packs, each of it has a value v and a weight w. Now you should find some packs, and the total of these value is max, total of

HDU 5340 Three Palindromes( 折半枚举+Manacher+记录区间 )

Three Palindromes Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 809    Accepted Submission(s): 240 Problem Description Can we divided a given string S into three nonempty palindromes? Input F

Eqs 折半枚举+二分查找 大水题

Eqs 题目抽象:a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 (*),给出a1,a2,a3,a4,a5.    ai属于[-50,50]. 求有多少序列   x1,x2,x3,x4,x5 ,xi属于 [-50,50]-{0}. 思路:折半枚举+二分查找 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #inclu

poj 2785 4 Values whose Sum is 0 折半枚举

题目链接:http://poj.org/problem?id=2785 枚举的一般思路就是先把所有的状态枚举出来 最后一次性判断该状态合法不合法 而折半枚举的思想是 先枚举一半的状态 把他们的状态存起来 排序 然后再枚举剩下一般 用目标反推前一半的期望状态 接下来在前一半的结果数组中查找是否有相应结果 之所以能优化是因为结果数组有序 就可以用二分搜索 复杂度从O(n^2 * n^2) 降到 O(n^2 * log(n^2))即(O(n^2 * log n)) 二分搜索的一个技巧 在有序数组中用二

NYOJ 1091 超大01背包(折半枚举)

这道题乍一看是普通的01背包,最最基础的,但是仔细一看数据,发现普通的根本没法做,仔细观察数组发现n比较小,利用这个特点将它划分为前半部分和后半部分这样就好了,当时在网上找题解,找不到,后来在挑战程序设计上找到了这个题,就拿来引用一下 挑选物品的方法总从2^n中,直接枚举肯定不行,因为n最大为40,但是如果n为20就可以了,这时候就要用到折半枚举,先枚举前一半,在枚举后一半.先把前把部分的选取方法对应的重量和价值总和记为w1, v1,这样后半部分寻找w2 <= W - w1时 使v2最大的选取方