参考 http://blog.csdn.net/wenlei_zhouwl/article/details/5992367
问题: 考虑在一个打印机上整齐地打印一段文章的问题。输入的正文是n个长度分别为L1、L2、……、Ln(以字符个数度量)的单词构成的序列。我们希望将这个段落在一些行上整齐地打印出来,每行至多M个字符。“整齐度”的标准如下:如果某一行包含从i到j的单词(i<j),且单词之间只留一个空格,则在行末多余的空格字符个数为 M - (j-i) - (Li+ …… + Lj),它必须是非负值才能让该行容纳这些单词。我们希望所有行(除最后一行)的行末多余空格字符个数的立方和最小。请给出一个动态规划的算法,来在打印机整齐地打印一段又n个单词的文章。分析所给算法的执行时间和空间需求。
分析:
构建数组a[i]代表包含1->i单词的最优“整齐度”——空格的立方总和。开始时,令a[0]=0。a[i]的递推式如下
W[k][i]代表将k到i的单词写入一行时,该行的多余空格数的立方。
每次计算a[i]时,循环k从i-1开始,直到某个k值使得 值为负,则跳出。
最终a[n]即为所求的最小立方总和。
程序:
#include<iostream> #include<string> #include<cstring> #include<cstdlib> #include<climits> using namespace std; int main(void) { void zq_print(void); zq_print(); return 0; } void zq_print(void) { //输入数据 int num,M,count; int p,q,i,j,flag; cin>>num; cin>>M; string* data=new string[num]; for(i=0;i<num;i++) { cin>>data[i]; } int *line=new int[num](); int *c=new int[num]; memset(c,0,num); p=0;flag=0;q=0;count=0; while(p<num) { line[q]=INT_MAX; for(i=p;i<num;) { /*计算的累加值*/ int sum=0; for(j=p;j<=i;j++) sum+=data[j].size(); //计算3次方 int temp=(M-i+p-sum)*(M-i+p-sum)*(M-i+p-sum); if(q>=1) temp+=line[q-1]; if(temp>=0 && (temp<line[q])) { flag=i; c[q]=flag; line[q]=temp; i++; } else break; //现在判断flag的值,是不是到达最后一行 } ++q; ++count; if(flag==num-1) break; else p=flag+1; } cout<<"count="<<count<<endl; for(i=0;i<count;i++) { cout<<c[i]<<"--->"<<line[i]<<endl; } //共count行 for(i=0;i<count;i++) { int begin=0; if(i>0) begin=c[i-1]+1; for(j=begin;j<=c[i];++j) cout<<data[j]<<" "; cout<<endl; } delete [] c; delete [] line; delete [] data; }