TakeoffYoung

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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)\n", 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\n", 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\n", r);
31                 t = r+1;
32                 if (s[n] - s[r] + n - r <= w) {
33                     return true;
34                 }
35             }
36         }
37     }
38 //    printf("false!!\n");
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\n", 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\n", l);
66     }
67     return 0;
68 }

 

posted on 2015-11-08 13:00  TakeoffYoung  阅读(208)  评论(0编辑  收藏  举报