UVA 714 Copying Books

给你m本书,每本a[i]页(0<=i<m),把他们分成k个区间,使这k个区间和的最大值最小。。
我们可以先找到这m本书的最大页数max, 和所有书的页数和sum,则这k个区间中 每个区间的区间和一定在[mmax,sum]中,(即分为m个区间,我们要的结果就是这m个数中的最大值,如果分为一个区间,结果就是所有数的页数和)

我们可以用二分先找到这个值(最大值中最小的数),判定条件就是能否分成k份。

剩下的就是根据这个值标记分开的位置,但为了在有多种结果时,前面区间尽量小,应从后往前分开,如果要求k分,我们只用了k-1分就完成了,剩下的要在前面按顺序补上(详看代码吧)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define sc(x)  scanf("%d", &x)
 6 #define sc1(x)  scanf("%lld", &x)
 7 #define sc2(x,y)    scanf("%d%d", &x, &y)
 8 #define pf(x)   printf("%lld", x)
 9 #define FOR(i,b,e)    for(int i=b;i<e;i++)
10 #define CL(x,y)      memset(x,y,sizeof(x))
11 using namespace std;
12 typedef long long ll;
13 const int MAX = 505;
14 int m, k;
15 ll arr[MAX], sum, Min, ans;
16 bool used[MAX];
17 inline int div(ll key)
18 {
19     CL(used, 0);
20     int cnt=0;
21     int pos=m-1;
22     while(pos>=0)
23     {
24         long long sum=0;
25         bool ok=true;
26         while(pos>=0 && sum+arr[pos] <= key)
27         {
28             ok=false;
29             sum += arr[pos];
30             --pos;
31         }
32         if(ok)
33         {
34             return k+1; // 返回一个大于k的数
35         }
36         if(pos>=0) used[pos] = true;
37         ++cnt;
38     }
39     return cnt;
40 }
41 ll binary()
42 {
43     ll left=Min, right=sum, mid;
44     while(left<right)
45     {
46         mid = (left+right)>>1;//右移1位,就是/2
47 //        cout << left << " " << right << " " << mid << endl;
48         if(div(mid)<=k)
49             right=mid;
50         else
51             left=mid+1;
52     }
53     return right;
54 }
55 
56 inline void output()
57 {
58     int cnt = div(ans);
59     for(int i=0; i<m-1 && cnt<k; i++)
60         if(!used[i])
61         {
62             used[i]=true;
63             ++cnt;
64         }
65     FOR(i, 0, m)
66     {
67         if(i) printf(" %lld",arr[i]);
68         else pf(arr[i]);
69         if(used[i])
70         {
71             printf(" /");
72         }
73     }
74     cout << endl;
75 }
76 int main()
77 {
78     int T;
79     sc(T);
80     while(T--)
81     {
82         sc2(m, k);
83         sum=0;
84         Min=0;
85         FOR(i, 0, m)
86         {
87             sc1(arr[i]);
88             sum += arr[i];
89             if(arr[i]>Min) Min=arr[i];
90         }
91         ans= binary();
92         output();
93     }
94     return 0;
95 }
View Code

还是有很多地方需要考虑,二分的思想很重要,重要是在div()中

posted @ 2015-04-05 16:38  PastLIFE  阅读(132)  评论(0编辑  收藏  举报