• UVa 714


      题目大意:有m本书,每本书有pi页,把这m本书分给k个人抄写,如何分配才能在最短的时间抄写完这m本书。

      最大值最小化问题:把一个包含n个正整数的序列划分成m个连续的子序列,设第i个序列的各数之和为S(i), 使得所有S(i)的最大值尽量小。序列最大值为max,所有数之和为sum,则所求答案必定在[max, sum]之间,通过二分法判断中值mid是否符合条件(把序列分为m份,每份均不超过mid)逐步缩小范围,直至求得解。

      其实,我觉得还是看代码来的直接,看书上说的东西半天也不理解说的什么意思,还是研究代码可以一点点地理解。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define MAXN 500+10
     6 
     7 long long p[MAXN];
     8 int m, k;
     9 bool cut[MAXN];
    10 
    11 bool judge(long long n)
    12 {
    13     long long sum = 0;
    14     int cnt = 0;
    15     for (int i = 0; i < m; i++)
    16     {
    17         if (sum + p[i] > n)
    18         {
    19             sum = 0;
    20             cnt++;
    21         }
    22         sum += p[i];
    23     }
    24     cnt++;
    25     if (cnt > k)  return false;
    26     return true;
    27 }
    28 
    29 int main()
    30 {
    31 #ifdef LOCAL
    32     freopen("in", "r", stdin);
    33 #endif
    34     int T;
    35     scanf("%d", &T);
    36     while (T--)
    37     {
    38         scanf("%d%d", &m, &k);
    39         long long sum = 0, lmax = 0;
    40         for (int i = 0; i < m; i++)
    41         {
    42             scanf("%lld", &p[i]);
    43             sum += p[i];
    44             lmax = max(lmax, p[i]);
    45         }
    46         long long low = lmax, high = sum;
    47         while (low < high)
    48         {
    49             long long mid = (low + high) / 2;
    50             if (judge(mid))  high = mid;
    51             else  low = mid + 1;
    52         }
    53         long long ans = low;
    54         int remain = k - 1;
    55         memset(cut, 0, sizeof(cut));
    56         sum = 0;
    57         for (int i = m-1; i >= 0; i--)
    58         {
    59             if (i+1 > remain && sum + p[i] <= ans)
    60             {
    61                 sum += p[i];
    62             }
    63             else
    64             {
    65                 cut[i] = true;
    66                 sum = p[i];
    67                 remain--;
    68             }
    69         }
    70         for (int i = 0; i < m; i++)
    71         {
    72             printf("%lld%s", p[i], (i == m-1) ? "
    " : " ");
    73             if (cut[i])  printf("/ ");
    74         }
    75     }
    76     return 0;
    77 }
    View Code

      最后的输出把我纠结地快疯了,本来也不是很麻烦,可是因为参考别人代码一会就把自己弄迷糊了,果然有些东西还是按自己思路写更自然、快速。

  • 相关阅读:
    php7安装Memcached扩展
    php7安装
    结束进程
    openssl 编译
    boost 编译
    php 与 c++ openssl 加密通信
    iptables 端口转发
    获取进程及父进程的两种方式
    windows 下获取父进程pid
    CentOS 64位系统 yum安装32位软件包的方法
  • 原文地址:https://www.cnblogs.com/xiaobaibuhei/p/3275266.html
Copyright © 2020-2023  润新知