题目:给你一段文字,让你对文字排版,每行的最大长度有限制L,有一个对于排版格式的权值公式:
P = sum((单词间空格-1)*(单词间空格-1))
求出P最小的一种排版,F相同时输出前面的空格最少的。
分析:DP。看见题目第一想到的就是利用dp,设F(i,j)是从第i个单词开始排版,到第j个单词结束的最小P
可以得到状态转移方程:
F(i,j)= min(F(i,k-1)+min_line(k,j)),i< k <= j 且 k到j的单词总长+j-k坏人空格不超过L
其中,min_line(k,j)是以k开始,j结束的一行的最小的P:
可以证明当每一行的单词确定后,平均分配中间的间隔,可以使得min_line最小。
最后,要注意计算的方向是从后向前,因为要保证前面的空格最少。
对于输出,保留上一行结束位置,每行单独计算即可。
(按顺序计算,后计算的优先级高,想一想求最短路时,如果保存路径使得前面路段最短,要逆向运算)
注意:数据的读入格式有点恶心。
// a+b = c, aa + bb = aa + (c-a)(c-a) = cc + 2aa - 2ac,最值在 2a = c #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> typedef struct dnode { char word[85]; int length; }data; data D[10005]; int sumL[10005]; int F[10005]; int E[10005]; void output( int i, int width, int max ) { if ( i < max ) { if ( E[i] > i+1 ) { //计算每行中具体的空格分布 int sblack = width-sumL[E[i]-1]+sumL[i-1]; int eblack = sblack/(E[i]-1-i); int nshort = (eblack+1)*(E[i]-1-i)-sblack; int count = 0; printf("%s",D[i].word); for ( int j = i+1 ; j < E[i] ; ++ j ) { for ( int k = 0 ; k < eblack ; ++ k ) printf(" "); if ( ++ count > nshort ) printf(" "); printf("%s",D[j].word); }printf("\n"); }else printf("%s\n",D[i].word);//自己独立一行 output( E[i], width, max ); } } int main() { int width,temp; while ( scanf("%d",&width) && width ) { getchar(); int count = 1; while ( (temp = getchar()) != ‘\n‘ ) { do { ungetc( temp, stdin ); scanf("%s",D[count].word); D[count].length = strlen(D[count].word); count ++; }while ( (temp = getchar()) != ‘\n‘ ); } sumL[0] = 0; for ( int i = 1 ; i < count ; ++ i ) sumL[i] = sumL[i-1]+D[i].length; F[count] = 0; for ( int i = count-1 ; i > 0 ; -- i ) { F[i] = F[i+1] + 500; E[i] = i+1; for ( int j = i+1 ; j < count && sumL[j]-sumL[i-1]+j-i <= width ; ++ j ) { //计算每行中具体的空格分布 int sblack = width-sumL[j]+sumL[i-1]; int eblack = sblack/(j-i); int nshort = (eblack+1)*(j-i)-sblack; int add = (j-i-nshort)*eblack*eblack+nshort*(eblack-1)*(eblack-1);//本行代价 if ( F[i] >= F[j+1] + add ) { F[i] = F[j+1] + add; E[i] = j+1; } } } output( 1, width, count ); printf("\n"); } return 0; }
附上两组比较恶心的数据:
input: 25 x x x x x xxxxxxxxxxxxxx x xxxxxxxxxxxx xxxxxxxxxxx x xxxxxxxxxxxxxx x x x x x 5 La la la output: x x x x x xxxxxxxxxxxxxx x xxxxxxxxxxxx xxxxxxxxxxx x xxxxxxxxxxxxxx x x x x x La la la
UVa 709 - Formatting Text,布布扣,bubuko.com
原文:http://blog.csdn.net/mobius_strip/article/details/22175897