线性动态规划-文件排版

题目

写电子邮件是有趣的,但不幸的是经常写不好看,主要是因为所有的行不一样长,你的上司想要发排版精美的电子邮件,你的任务是为他编写一个电子邮件排版程序。

完成这个任务最简单的办法是在太短的行中的单词之间插入空格,但这并不是最好的方法,考虑如下例子:


This is the example you are

actually considering.

假设我们想将第二行变得和第一行一样长,靠简单地插入空格则我们将得到如下结果:


This is the example you are

actually considering.

但这太难看了,因为在第二行中有一个非常大的空白,如果将第一行的单词“are”移到下一行我们将得到较好的结果:


This is the example you

are actually considering.

当然,这必须对难看程度进行量化。因此我们必须给出单词之间的空格的难看程度,一个包含N个空格符的空白段,其难看程度值为(n-1)2,程序的目的是使难看程度的总和最小化。例如,第一个例子的难看程度是1+7*7=50,而第二个例子的难看程度仅为1+1+1+4+1+4=12。

输出时,每一行的开头和结尾处都必须是一个单词,即每行开头和结尾处不能有空白。唯一例外的是该行仅有一个单词组成的情况,对于这种情况你可将单词放在该行开头处输出,此时如果该单词比该行应有的长度短则我们指定它的最坏程度为500,当然在这种情况下,该行的实际长度即为该单词的长度。

输入描述 Input Description
输入文件第一行是一个整数N,表示该段要求达到的宽度,1<=N<=80。该段文章由一个或多个单词组成,单词由ASCII码值为33到126(包含33和126)的字符组成,单词与单词之间用空格隔开(可能超过一个)。单词长度不会超过段落要求达到的宽度。一段文字所有单词的总长度不会超过10000个字符,任何一行都不会超过100个字符,任何一个单词都在同一行内。

输出描述 Output Description
对于每个段落,找出使其难看程度最小的排版形式并输出句子:“Minimal badness is B.”,B是指按可能的最好排版形式会发生的难看程度值。注意排版后文本行数任意,多余的空格也可删除。

样例输入 Sample Input
28
This is the example you are
actually considering.

样例输出 Sample Output
Minimal badness is 12.

解题思路

dp[i]表示第i个单词放在当前行的最后的最小难看程度。因为题目规定了每一行的开始和结束必须是单词。
dp[i] <= dp[j] + tmp tmp是[j + 1, i] 的最小值。

代码

#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
using namespace std;


int width; 
int len[10010];
int dp[10010];
int nums;
int main() {
    cin >> width;
    string tmp;
    nums = 0;
    while(cin >> tmp) {
        nums ++;
        len[nums] = len[nums - 1] + tmp.size();

    }

    memset(dp,0,sizeof(dp));
    for(int i = 1;i <= nums;i ++) {
        if(len[i] - len[i - 1] == width) dp[i] = dp[i - 1];
        else dp[i] = dp[i - 1] + 500;

        for(int j = i - 2;j >= 0;j --) {
            //j + 1 ---> i
            int tot = i - j - 1; //i - (j + 1) + 1 - 1;
            int blanks = width - (len[i] - len[j]);  
            if(blanks < tot) continue; // widht - (len[i] - len[j]) < i - j - 1
            int avg = blanks / tot;
            int rmd = blanks % tot;

            int tmp =  rmd * (avg * avg) + (tot - rmd) * (avg - 1) * (avg - 1);
            dp[i] = min(dp[i],dp[j] + tmp);

        }
    }
    printf("Minimal badness is %d.\n",dp[nums]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章