• 【uva 714】Copying Books(算法效率--二分+贪心)


    题意:将1个含N个正整数的序列划分成K个连续的子序列,使每段的和的最大值尽量小,问字典序最小的划分方案。

    解法:由于是连续的数的“最大值最小”,便可想到二分每段的最大值,若这时可分成<=K段,则这个最大值成立,再继续二分。

    输出方案需要用到贪心策略, 先从后往前贪心求得最小划分的段数M,若M不足K,则直接使K-M个数单独划分为一段,保证字典序最小。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 const int N=510,D=(int)1e7+10;//N*D long long
     7 typedef long long LL;
     8 int a[N],v[N];
     9 int n,k;
    10 
    11 int check(LL x)
    12 {
    13     LL t=1,h=0;
    14     for (int i=1;i<=n;i++)
    15     {
    16       h+=a[i];
    17       if (h>x) h=a[i],t++;
    18     }
    19     return t<=k;
    20 }
    21 int main()
    22 {
    23     int T;
    24     scanf("%d",&T);
    25     while (T--)
    26     {
    27       long long h=0,mx=0;
    28       scanf("%d%d",&n,&k);
    29       for (int i=1;i<=n;i++)
    30         scanf("%d",&a[i]),h+=a[i],mx=mx>a[i]?mx:a[i];
    31       LL l=mx,r=h,mid,ans=1<<30;
    32       while (l<=r)
    33       {
    34         mid=(l+r)>>1;
    35         int tmp=check(mid);
    36         if (tmp) ans=mid,r=mid-1;
    37         else l=mid+1;
    38       }
    39       int e=1; h=0;
    40       for (int i=n;i>=1;i--)
    41       {
    42         h+=a[i], v[i]=0;
    43         if (h>ans) h=a[i],e++,v[i]=1;
    44       }
    45       h=0;
    46       for (int i=1;i<=n;i++)
    47       {
    48         printf("%d",a[i]);
    49         if (v[i]) printf(" /");
    50         else if (h<k-e) printf(" /"),h++;
    51         if (i<n) printf(" ");
    52       }
    53       printf("
    ");
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    C#操作符??和?:
    使用Windows8开发Metro风格应用一
    使用Windows8开发Metro风格应用二
    Win8使用技巧
    详解 xls xlst xml 一
    SqlDataAdapter DataSet DataTable 详解
    DataSet 与 xml
    FileTracker : error FTK1011编译错误
    我的CHROME插件
    Komodo升级错误
  • 原文地址:https://www.cnblogs.com/konjak/p/6017604.html
Copyright © 2020-2023  润新知