Processing math: 100%

print neatly 整齐打印 算法导论

作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4098562.html

题目链接:print neatly 整齐打印 算法导论

考虑在一个打印机上整齐地打印一段文章的问题。输入的正文是n个长度分别为L1,L2,,Ln(以字符个数度量)的单词构成的序列。我们希望将这个段落在一些行上整齐地打印出来,每行至多M个字符。“整齐度”的标准如下:如果某一行包含从i到j的单词(i<j),且单词之间只留一个空格,则在行末多余的空格字符个数为 M(ji)(Li++Lj),它必须是非负值才能让该行容纳这些单词。我们希望所有行(除最后一行)的行末多余空格字符个数的立方和最小。请给出一个动态规划的算法,来在打印机整齐地打印一段又n个单词的文章。分析所给算法的执行时间和空间需求。

 

使用动态规划算法,dp[i]表示从第一个单词到第i个单词所需要的最小代价。对于每一个单词分别考虑自己单独一行,和前一个单独占据一行 和前k个单词占据一行的情况,其中从ki的字符串长度不超过每行最多所能容纳的字符串长度m,最后从后向前遍历dp数组,计算分别把最后的k个单词作为最后一行,且不计算代价的情况下最小的代价。

 

代码如下:

复制代码
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>  
 6 #include  <limits.h>
 7 #define     MAXN 2010
 8 using namespace std;  
 9 typedef  long long LL;
10 LL dp[MAXN], w[MAXN][MAXN];  
11 int len[MAXN];  
12 int n, m;
13 LL solve()
14 {
15     memset(dp, 0, sizeof(dp));
16     memset(w, -1, sizeof(w));
17     for( int i = 0 ; i <= n ; i++ )
18     {
19         for( int j = 0 ; j <= n ; j++ )
20         {
21             w[0][j] = 0;
22         }
23     }
24     for( int i = 1 ; i <= n ; i++ )
25     {
26         for( int j = i ; j <= n ; j++ )
27         {
28             int tmp = m - (j-i) - (len[j]-len[i-1]);
29             if( tmp < 0 )
30             {
31                 break;
32             }
33             w[i][j] = tmp*tmp*tmp;
34         }
35     }
36     dp[0]  = 0;
37     for( int i = 1 ; i <= n ; i++ )
38     {
39         dp[i] = dp[i-1]+w[i][i];
40         for( int j = i-1 ; j >= 0 ; j-- )
41         {
42             if( w[j+1][i] < 0 ) break;
43             dp[i] = min(dp[i], dp[j] + w[j+1][i]);
44         }
45    }
46     LL res = dp[n];
47     for( int i = n ; i >= 0 && w[i][n] >= 0 ; i-- )
48     {
49         res = min(res, dp[i-1]);
50     }
51     return res;
52 }
53 int main(int argc, char *argv[])
54 {
55     while( scanf("%d%d", &n, &m)!=EOF )
56     {
57         len[0] = 0;
58         for( int i = 1 ; i <= n ; i++ )
59         {
60             scanf("%d", &len[i]);
61         }
62         for( int i = 2 ; i <= n ; i++ )
63         {
64             len[i] = len[i-1] + len[i];
65         }
66         printf("%lld\n", solve());
67     }
68 }
69 //input:(n, m, arr[i])
70 //5 5
71 //4 1 1 3 3
72 //5 6
73 //1 3 3 2 3
74 //output:
75 //17
76 //1
View Code
复制代码

 

posted @   jostree  阅读(1929)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示