【NOI2009】 诗人小G

题目描述
题目描述
 诗人小G
 【问题描述】
     小G是一个出色的诗人,经常作诗自娱自乐。但是,他一直被一件事情所困扰,那就是诗的排版问题。
 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中, 注意一行中可以放的句子数目是没有限制的。小G给每首诗定义了一个行标准长度(行的长度为一行中符号的总个数),他希望排版后每行的长度都和行标准长度相差不远。显然排版时,不应改变原有的句子顺序,并且小G不允许把一个句子分在两行或者更多的行内。在满足上面两个条件的情况下,小G对于排版中的每行定义了一个不协调度, 为这行的实际长度与行标准长度差值绝对值的P次方,而一个排版的不协调度为所有行不协调度的总和。
 小G最近又作了几首诗,现在请你对这首诗进行排版,使得排版后的诗尽量协调(即不协调度尽量小),并把排版的结果告诉他。
 【输入文件】
     输入文件poet.in包含多组数据。
 第一行包含一个整数T,表示诗的数量,接下来是T首诗,这里一首诗即为一组数据。每组数据的第一行包含三个由空格分隔的正整数N、L、P,其中N表示这首诗句子的数目,L表示这首诗的行标准长度,P的含义见问题描述。从第2行开始,每行为一个句子,句子由英文字母、数字、标点符号等符号组成(ASCII码33~127, 但不包含 ‘-’)。
 【输出文件】
     输出文件为poet.out。
 对于每组数据,若最小的不协调度不超过1018,则第一行一个数表示不协调度,接下来若干行,表示你排版之后的诗。注意:在同一行的相邻两个句子之间需要用一个空格分开。如果有多个可行解,它们的不协调度都是最小值,则输出任意一个解均可。若最小的不协调度超过1018,则输出"Too hard to arrange"(不包含引号)。每组数据结束后输出"--------------------"(不包括引号),共20个"-","-"的ASCII码为45,请勿输出多余的空行或者空格。
 【输入样例】
 4
 4 9 3
 brysj,
 hhrhl.
 yqqlm,
 gsycl.
 4 9 2
 brysj,
 hhrhl.
 yqqlm,
 gsycl.
 1 1005 6
 poet
 1 1004 6
 poet
 【输出样例】
 108
 brysj,
 hhrhl.
 yqqlm,
 gsycl.
 --------------------
 32
 brysj, hhrhl.
 yqqlm, gsycl.
 --------------------
 Too hard to arrange
 --------------------
 1000000000000000000
 poet
 --------------------
 【样例说明】
 前两组输入数据中每行的实际长度均为6,后两组输入数据每行的实际长度均为4。一个排版方案中每行相邻两个句子之间的空格也算在这行的长度中(可参见样例中第二组数据)。每行末尾没有空格。
 【评分方法】
 本题设有部分分,当你的程序对于该测试点内每组数据计算得出的不协调度最小值都正确时,能得到本测试点70%的分数。在此情况下,若每组数据的排版方案都合法并且得出的不协调度都与输出的相等,则能得到本测试点剩下30%的分数。注意,输出格式错误可能会导致本测试点不得分。
 
 
 【数据规模和约定】
 总共10个测试点,数据范围满足:
 
 测试点                 T                      N                     L                     P
 110181005
 21020006000010
 31020006000010
 4510000020010
 5510000020010
 651000003000000               2
 751000003000000               2
 85100000300000010
 95100000300000010
 105100000300000010
 所有测试点中均满足句子长度不超过30。

 

题解

 

解法1/2:贪心与动态规划
 1 program poet;
 2 var
 3   i,j,q:longint;
 4   t:array[0..100000] of string;
 5   n,l,p,tmp,max:int64;
 6   f,s,g:array[0..100000] of int64;
 7 //=========================
 8 function quick(x,y:int64):int64;
 9 var
10   t,k:int64;
11 begin
12   //writeln(x,' ',y);
13   t:=1; k:=x;
14   while y>0 do
15   begin
16     if y and 1=1 then
17     begin
18       if t/max*k>1 then exit(max);
19       t:=t*k;
20     end;
21     if k/max*k>1 then k:=max else k:=k*k;
22     y:=y >> 1;
23   end;
24   exit(t);
25 end;
26 //=========================
27 procedure huisu(x:longint);
28 var
29   i:longint;
30 begin
31   if g[x]>0 then huisu(g[x]);
32   for i:=g[x]+1 to x-1 do write(t[i],' ');
33   writeln(t[x]);
34 end;
35 //=========================
36 begin
37   assign(input,'poet.in'); reset(input);
38   assign(output,'poet.out'); rewrite(output);
39   max:=1;
40   for i:=1 to 18 do max:=max*10;
41   inc(max);
42   read(q);
43   while q>0 do
44   begin
45     dec(q);
46     fillchar(s,sizeof(s),0);
47     fillchar(f,sizeof(f),0);
48     readln(n,l,p);
49     for i:=1 to n do
50     begin
51       readln(t[i]);
52       s[i]:=s[i-1]+length(t[i]);
53     end;
54     for i:=1 to n do
55     begin
56       f[i]:=max;
57       for j:=i-1 downto 0 do
58       begin
59         if s[i]-s[j]>=l shl 1 then break;
60         tmp:=f[j]+quick(abs(s[i]-s[j]+i-j-1-l),p);
61         if f[i]>tmp then
62         begin
63           f[i]:=tmp;
64           g[i]:=j;
65         end;
66       end;
67     end;
68     if f[n]>=max then writeln('Too hard to arrange') else
69     begin
70       writeln(f[n]);
71       huisu(n);
72     end;
73     writeln('--------------------');
74   end;
75   close(input); close(output);
76 end.

 

解法3:斜率优化
 1 program poet;
 2 var
 3   i,j,q:longint;
 4   t:array[0..100000] of string;
 5   n,l,p,tmp,max,fl,fr,std:int64;
 6   f,s,g,dui,tx:array[0..100000] of int64;
 7 //=========================
 8 function quick(x,y:int64):int64;
 9 var
10   t,k:int64;
11 begin
12   t:=1; k:=x;
13   while y>0 do
14   begin
15     if y and 1=1 then
16     begin
17       if t/max*k>1 then exit(max);
18       t:=t*k;
19     end;
20     if k/max*k>1 then k:=max else k:=k*k;
21     y:=y >> 1;
22   end;
23   exit(t);
24 end;
25 //=========================
26 procedure huisu(x:longint);
27 var
28   i:longint;
29 begin
30   if g[x]>0 then huisu(g[x]);
31   for i:=g[x]+1 to x-1 do write(t[i],' ');
32   writeln(t[x]);
33 end;
34 //=========================
35 function calc(k,j:longint):extended;
36 begin
37   exit((f[k]+sqr(tx[k])-f[j]-sqr(tx[j]))/(tx[k]-tx[j]));
38 end;
39 //=========================
40 begin
41   assign(input,'poet.in'); reset(input);
42   assign(output,'poet.out'); rewrite(output);
43   max:=1;
44   for i:=1 to 18 do max:=max*10;
45   inc(max);
46   read(q);
47   while q>0 do
48   begin
49     dec(q);
50     fillchar(s,sizeof(s),0);
51     fillchar(f,sizeof(f),0);
52     readln(n,l,p);
53     for i:=1 to n do
54     begin
55       readln(t[i]);
56       s[i]:=s[i-1]+length(t[i]);
57     end;
58     if p=2 then
59     begin
60       fl:=0; fr:=1; dui[1]:=0;
61       for i:=1 to n do
62       begin
63         std:=(s[i]+i-l-1) shl 1;
64         while (fl<fr-1)and(calc(dui[fl+1],dui[fl+2])<=std) do inc(fl);
65         j:=dui[fl+1];
66         f[i]:=f[j]+quick(abs(s[i]-s[j]+i-j-1-l),p);
67         g[i]:=j;
68         tx[i]:=s[i]+i;
69         while (fl<fr-1)and(calc(dui[fr-1],dui[fr])>calc(dui[fr],i)) do dec(fr);
70         inc(fr); dui[fr]:=i;
71       end;
72     end else
73     begin
74       for i:=1 to n do
75       begin
76         f[i]:=max;
77         for j:=i-1 downto 0 do
78         begin
79           if s[i]-s[j]>=l shl 1 then break;
80           tmp:=f[j]+quick(abs(s[i]-s[j]+i-j-1-l),p);
81           if f[i]>tmp then
82           begin
83             f[i]:=tmp;
84             g[i]:=j;
85           end;
86         end;
87       end;
88     end;
89 
90     if f[n]>=max then writeln('Too hard to arrange') else
91     begin
92       writeln(f[n]);
93       huisu(n);
94     end;
95     writeln('--------------------');
96   end;
97   close(input); close(output);
98 end.

 

解法4:单调性优化
  1 program poet;
  2 type
  3   ty=record
  4     l,r,x:longint;
  5   end;
  6 
  7 var
  8   i,j,q:longint;
  9   t:array[0..100000] of string;
 10   n,l,p,max,top:int64;
 11   f,s:array[0..100000] of extended;
 12   _f:array[0..100000] of int64;
 13   g:array[0..100000] of longint;
 14   inn:array[0..100000] of ty;
 15 //==================
 16 function quick(x,y:longint):extended;
 17 var
 18   t,k:extended;
 19 begin
 20   t:=1; k:=x;
 21   while y>0 do
 22   begin
 23     if y and 1=1 then t:=t*k;
 24     k:=k*k;
 25     y:=y >> 1;
 26   end;
 27   exit(t);
 28 end;
 29 //==================
 30 function _quick(x,y:longint):int64;
 31 var
 32   t,k:int64;
 33 begin
 34   t:=1; k:=x;
 35   while y>0 do
 36   begin
 37     if y and 1=1 then
 38     begin
 39       if t/max*k>1 then exit(max);
 40       t:=t*k;
 41     end;
 42     if k/max*k>1 then k:=max else k:=k*k;
 43     y:=y >> 1;
 44   end;
 45   exit(t);
 46 end;
 47 //==================
 48 procedure huisu(x:longint);
 49 var
 50   i:longint;
 51 begin
 52   if g[x]>0 then huisu(g[x]);
 53   for i:=g[x]+1 to x-1 do write(t[i],' ');
 54   writeln(t[x]);
 55 end;
 56 //==================
 57 function getf(i,j:longint):extended;
 58 begin
 59   exit(f[j]+quick(trunc(abs(s[i]-s[j]+i-j-1-l)),p));
 60 end;
 61 //==================
 62 function _getf(i,j:longint):int64;
 63 begin
 64   if _f[j]>=max then exit(max);
 65   exit(_f[j]+_quick(trunc(abs(s[i]-s[j]+i-j-1-l)),p));
 66 end;
 67 //==================
 68 procedure change(x:longint);
 69 var
 70   sl,sr,m,t:longint;
 71 begin
 72   while (inn[top].l>x)and(getf(inn[top].l,inn[top].x)>getf(inn[top].l,x)) do
 73   begin
 74     inn[top-1].r:=inn[top].r;
 75     dec(top);
 76   end;
 77   t:=0; sl:=inn[top].l; sr:=inn[top].r;
 78   if sl<x+1 then sl:=x+1;
 79   while sl<=sr do
 80   begin
 81     m:=(sl+sr) >> 1;
 82     if getf(m,inn[top].x)>getf(m,x) then
 83     begin
 84       t:=m; sr:=m-1;
 85     end else sl:=m+1;
 86   end;
 87   if t=0 then exit;
 88   inn[top].r:=t-1;
 89   inc(top);
 90   inn[top].l:=t;
 91   inn[top].x:=x;
 92   inn[top].r:=n;
 93 end;
 94 //==================
 95 begin
 96   assign(input,'poet.in'); reset(input);
 97   assign(output,'poet.out'); rewrite(output);
 98   max:=1;
 99   for i:=1 to 18 do max:=max*10;
100   inc(max);
101   read(q);
102   while q>0 do
103   begin
104     dec(q);
105     readln(n,l,p);
106     s[0]:=0; f[0]:=0;
107     for i:=1 to n do
108     begin
109       readln(t[i]);
110       s[i]:=s[i-1]+length(t[i]);
111     end;
112     top:=1;
113     inn[top].x:=0; inn[top].l:=1; inn[top].r:=n;
114     j:=1;
115     for i:=1 to n do
116     begin
117       while i>inn[j].r do inc(j);
118       f[i]:=getf(i,inn[j].x);
119       g[i]:=inn[j].x;
120       change(i);
121     end;
122     for i:=1 to n do _f[i]:=_getf(i,g[i]);
123     if _f[n]>=max then writeln('Too hard to arrange') else
124     begin
125       writeln(_f[n]);
126       huisu(n);
127     end;
128     writeln('--------------------');
129   end;
130   close(input); close(output);
131 end.
posted @ 2012-05-16 09:02  datam  阅读(759)  评论(0编辑  收藏  举报