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 }

 

posted @ 2016-04-20 20:23  罗茜  阅读(289)  评论(0编辑  收藏  举报