• uvalive-6190(二分+dp验证)


    Beautiful Spacing

    链接

    题意:

      文本每行有w列,有n个单词。排列规则如下:

      1、每两个单词之间必须有空格

      2、除了最后一行,每行第一个单词第一个字母必须顶格,最后一个单词最后一个字母必须在最后一格。

      3、同一个单词不能换行

      要使得最大间隔最小

    解决:

      使最大值最小的问题,显然二分。

      验证的时候不能像一般题目贪心验证。

      dp[i]为第i个单词做开头的时候,对于待验证值x,枚举可行结尾j,则每个可行结尾j对应了下一个可行开头 j + 1,这样一来状态转移就出来了,朴素的dp中n^2的复杂度被减枝很多。再者,如果 [i, j]这一段中,每两个的单词之间空位都是x,且仍不能填满一行,则[i+1, j]一定也不能达到填满一行的要求。所以这个时候,对于每个可行开头i, 枚举可行结尾的时候,不用再从i+1开始。

     1 #include <bits/stdc++.h>
     2 
     3 const int MAXN = 50000+10;
     4 
     5 int w, n;
     6 int a[MAXN];
     7 int s[MAXN];
     8 bool dp[MAXN];
     9 
    10 bool check(int x)
    11 {
    12 //    printf("check(%d)
    ", x);
    13     memset(dp, false, sizeof(dp));
    14     dp[1] = true;
    15     if (s[n] + n - 1 <= w)
    16         return true;
    17     for (int l = 1, t = 2; l <= n; ++l) {
    18         if (dp[l] == true) {
    19             for (int r = std::max(l+1, t); r <= n; ++r) {
    20                 int cnt = r - l + 1;
    21                 int len = s[r] - s[l-1];
    22                 int max_len = (cnt-1)*x + len;
    23                 int min_len = cnt - 1 + len;
    24 //                printf("l = %d, r = %d, min_len = %d, max_len = %d
    ", l, r, min_len, max_len);
    25                 if (min_len > w)
    26                     break;
    27                 if (max_len < w)
    28                     continue;
    29                 dp[r + 1] = true;
    30 //                printf("r = %d
    ", r);
    31                 t = r+1;
    32                 if (s[n] - s[r] + n - r <= w) {
    33                     return true;
    34                 }
    35             }
    36         }
    37     }
    38 //    printf("false!!
    ");
    39     return false;
    40 
    41 }
    42 
    43 int main()
    44 {
    45 
    46     while (~scanf("%d%d", &w, &n)) {
    47         if (w == 0 && n == 0)
    48             break;
    49         s[0] = 0;
    50         for (int i= 1; i <= n; ++i)
    51             scanf("%d", a+i), s[i] = s[i-1] + a[i];
    52         if (s[n] + n-1 <= w) {
    53             printf("%d
    ", 1);
    54             continue;
    55         }
    56         int l = 1, r = w;
    57         while (l <= r) {
    58             int mid = l + r >> 1;
    59             if (check(mid)) {
    60                 r = mid - 1;
    61             }
    62             else
    63                 l = mid + 1;
    64         }
    65         printf("%d
    ", l);
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    自愿如此 四 内观
    自愿如此· 三 不做解释
    自愿如此·序言
    排序算法 (08.堆排序)
    2.2 ES6 解构赋值
    2.1 ES6 let 与 const
    ES6学习 (01. 内容概况)
    vue 技术栈进阶 (07. ajax 请求实战)
    vue技术栈进阶(06.状态持久化, 严格模式, 数据双向绑定问题)
    vue技术栈进阶(05. mutations, actions)
  • 原文地址:https://www.cnblogs.com/takeoffyoung/p/4947175.html
Copyright © 2020-2023  润新知