線性動態規劃-文件排版

題目

寫電子郵件是有趣的,但不幸的是經常寫不好看,主要是因爲所有的行不一樣長,你的上司想要發排版精美的電子郵件,你的任務是爲他編寫一個電子郵件排版程序。

完成這個任務最簡單的辦法是在太短的行中的單詞之間插入空格,但這並不是最好的方法,考慮如下例子:


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]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章