题目描述
题目描述 诗人小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 1 ≤10 ≤18 ≤100 ≤5 2 ≤10 ≤2000 ≤60000 ≤10 3 ≤10 ≤2000 ≤60000 ≤10 4 ≤5 ≤100000 ≤200 ≤10 5 ≤5 ≤100000 ≤200 ≤10 6 ≤5 ≤100000 ≤3000000 2 7 ≤5 ≤100000 ≤3000000 2 8 ≤5 ≤100000 ≤3000000 ≤10 9 ≤5 ≤100000 ≤3000000 ≤10 10 ≤5 ≤100000 ≤3000000 ≤10 所有测试点中均满足句子长度不超过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.