zoukankan      html  css  js  c++  java
  • 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()中

  • 相关阅读:
    关于类的继承与初始化顺序
    大数据协作框架
    关于委托和线程
    Hive高级
    聚集索引和非聚集索引
    Hadoop生态优秀文章集锦
    hive深入使用
    hive常规配置及常用命令使用
    HBase核心技术点
    zipkin环境搭建
  • 原文地址:https://www.cnblogs.com/ghostTao/p/4394325.html
Copyright © 2011-2022 走看看