[BZOJ1563]詩人小G(1d1d動態規劃)

來源:互聯網
上載者:User
題目描述 Description

小G是一個出色的詩人,經常作詩自娛自樂。但是,他一直被一件事情所困擾,那就是詩的排版問題。
一首詩包含了若干個句子,對於一些連續的短句,可以將它們用空格隔開並放在一行中,注意一行中可以放的句子數目是沒有限制的。小G給每首詩定義了一個行標準長度(行的長度為一行中符號的總個數),他希望排版後每行的長度都和行標準長度相差不遠。顯然排版時,不應改變原有的句子順序,並且小G不允許把一個句子分在兩行或者更多的行內。在滿足上面兩個條件的情況下,小G對於排版中的每行定義了一個不協調度, 為這行的實際長度與行標準長度差值絕對值的P次方,而一個排版的不協調度為所有行不協調度的總和。
小G最近又作了幾首詩,現在請你對這首詩進行排版,使得排版後的詩盡量協調(即不協調度盡量小),並把排版的結果告訴他。 輸入描述 Input Description

本題中包含多組測試資料。
輸入檔案中的第一行為一個整數T,表示詩的數量。
接下來為T首詩,這裡一首詩即為一組測試資料。每組測試資料中的第一行為三個由空格分隔的正整數N,L,P,其中:N表示這首詩句子的數目,L表示這首詩的行標準長度,P的含義見問題描述。
從第二行開始,每行為一個句子,句子由英文字母、數字、標點符號等符號組成(ASCII碼33~127,但不包含’-‘)。 輸出描述 Output Description

對於每組測試資料,若最小的不協調度不超過10^18,則第一行為一個數,表示不協調度。接下來若干行,表示你排版之後的詩。注意:在同一行的相鄰兩個句子之間需要用一個空格分開。
如果有多個可行解,它們的不協調度都是最小值,則輸出任意一個解均可。若最小的不協調度超過10^18,則輸出“Too hard to arrange”(不含引號)。每組測試資料結束後輸出“——————–”(不含引號),共20個“-”,“-”的ASCII碼為45,請勿輸出多餘的空行或者空格。
由於缺少special judge,因此在這裡只要求輸出最小的不協調度。格式不變,依然以”-“分割。 範例輸入 Sample Input

4
4 9 3
brysj,
hhrhl.
yqqlm,
gsycl.
4 9 2
brysj,
hhrhl.
yqqlm,
gsycl.
1 1005 6
poet
1 1004 6
poet 範例輸出 Sample Output

108
−−−−−−−−−−−−−−−−−−−− --------------------
32
−−−−−−−−−−−−−−−−−−−− --------------------
Too hard to arrange
−−−−−−−−−−−−−−−−−−−− --------------------
1000000000000000000
−−−−−−−−−−−−−−−−−−−− -------------------- 資料範圍及提示 Data Size & Hint

【範例說明】
前兩組輸入資料中每行的實際長度均為6,後兩組輸入資料每行的實際長度均為4。一個排版方案中每行相鄰兩個句子之間的空格也算在這行的長度中(可參見範例中第二組資料)。每行末尾沒有空格。

所有測試點中均滿足句子長度不超過30。 題解

30分演算法:
1,2,3組資料:樸素動態規劃,轉移方程:
f[i]=min(f[j]+|s[i]−s[j]+i−j−1−L|p)。 f[i] = min(f[j] + |s[i] - s[j] + i - j - 1 - L| ^ p)。
100分演算法:
既然直接dp只有30分,那麼我們該想如何進行最佳化。
我們可以看出這是一個1D1D動態規劃,那麼決策區間就是連續的段落,於是我們維護一個上凸殼,每次更新的時候用二分就好了,注意也要用隊列來最佳化。
注意資料比較大,用long double 算完轉long long輸出。 代碼

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>typedef long double ll;#define inf 9000000000000000000#define MAX 1000000000000000000LLusing namespace std;int t,n,l,p,top;ll sum[100005],f[100005],from[100005];char ch[100005][35];struct nod{    int l,r,p;    nod(){}    nod(int a,int b,int c):l(a),r(b),p(c){}}q[100005];inline ll read() {    ll x=0;    char c=getchar();    while(c<'0' || c>'9') c=getchar();    while(c<='9' && c>='0'){x=x*10+c-'0';c=getchar();}    return x; }inline ll pow(ll x) {    if(x<0) x=-x;    ll ans=1;    for(int i=1;i<=p;i++) ans*=x;    return ans;}inline ll cal(int j,int i) {    return f[j]+pow(sum[i]-sum[j]+(i-j-1)-l);}int find(nod a,int b) {    int l=a.l,r=a.r;    while(l<=r) {        int mid=l+r>>1;        if(cal(a.p,mid)<cal(b,mid)) l=mid+1;        else r=mid-1;    }    return l;}void dp() {    int hd=1,tl=0;    q[++tl]=nod(0,n,0);    for(int i=1;i<=n;i++) {        if(hd<=tl && i>q[hd].r) hd++;        f[i]=cal(q[hd].p,i);from[i]=q[hd].p;        if(hd>tl || cal(i,n)<=cal(q[tl].p,n)) {            while(hd<=tl && cal(i,q[tl].l)<=cal(q[tl].p,q[tl].l)) tl--;            if(hd>tl) q[++tl]=nod(i,n,i);            else {                int t=find(q[tl],i);                q[tl].r=t-1;                q[++tl]=nod(t,n,i);            }        }    }}int main() {    t=read();    while(t--) {        n=read(),l=read(),p=read();        for(int i=1;i<=n;i++) scanf("%s",ch[i]);        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+strlen(ch[i]);        dp();        if(f[n]>MAX) printf("Too hard to arrange\n");        else printf("%lld\n",(long long)(f[n]));        printf("--------------------\n");    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.