题意:给出一个句子和要求整理后每行包含的字符数,要求将其整理为一种总badness最小的形式。设每个空格长度为n,单个空格的badness计算公式为(n-1)^2。总badness等于所有空格的badness的总和。给出整理后的格式。在badness最小的前提下,在分配一行中的空格时要让前面的空格尽量少。如果一个单词单占一行,badness为500。

分析:动态规划。f[i]表示前i个单词的最小badness是多少。f[i]=f[i-j]+cost(i-j,j);。cost(a,b)表示从单词a+1到单词b的放在一行中最小badness是多少。

并用from[i]存储f[i]是从哪个位置计算得来的值,即最后一次更新f[i]时i-j是几,即f[i]所在行的上一行的最后一个单词是第几个。

我们利用from数组可以求出最佳方案,然后按照题中要求输出即可。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. using namespace std;
  6.  
  7. const int maxn = ;
  8.  
  9. int n, wordsnum;
  10. string words[maxn];
  11. int sum[maxn];
  12. int f[maxn][maxn];
  13. int from[maxn][maxn];
  14.  
  15. void turntowords(string st)
  16. {
  17. int i = ;
  18.  
  19. while ()
  20. {
  21. i = ;
  22. while (st[i] != ' ' && i < signed(st.length()))
  23. i++;
  24. words[wordsnum++] = st.substr(, i);
  25. sum[wordsnum] = i + sum[wordsnum - ];
  26. if (i == signed(st.length()))
  27. break;
  28. st.erase(, i);
  29. while (st[] == ' ')
  30. st.erase(, );
  31. }
  32. }
  33.  
  34. void init()
  35. {
  36. string st;
  37.  
  38. wordsnum = ;
  39. memset(sum, , sizeof(sum));
  40. getchar();
  41. while ()
  42. {
  43. getline(cin, st);
  44. if (st == "")
  45. break;
  46. turntowords(st);
  47. }
  48. }
  49.  
  50. int cost(int start, int end)
  51. {
  52. int left, right, tot, len;
  53.  
  54. if (end - start == )
  55. return ;
  56. tot = n - (sum[end] - sum[start]);
  57. len = tot / (end - start - );
  58. left = end - start - - tot % (end - start - );
  59. right = tot % (end - start - );
  60. return left * (len - ) * (len - ) + right * len * len;
  61. }
  62.  
  63. void work()
  64. {
  65. int i, j, k;
  66.  
  67. memset(f, -, sizeof(f));
  68. f[][] = ;
  69. for (i = ; i <= wordsnum; i++)
  70. for (j = ; j <= wordsnum; j++)
  71. for (k = ; k <= j && j - k >= i - && n - (sum[j] - sum[j - k]) >= k - ; k++)
  72. if (f[i - ][j - k] != - && (f[i][j] > f[i - ][j - k] + cost(j - k, j) || f[i][j] == -))
  73. {
  74. f[i][j] = f[i - ][j - k] + cost(j - k, j);
  75. from[i][j] = k;
  76. }
  77. }
  78.  
  79. void printline(int start, int end)
  80. {
  81. int left, tot, len, i, j;
  82.  
  83. if (end - start == )
  84. {
  85. cout << words[start] << endl;
  86. return;
  87. }
  88. tot = n - (sum[end] - sum[start]);
  89. len = tot / (end - start - );
  90. left = end - start - - tot % (end - start - );
  91. for (i = start; i < end - ; i++)
  92. {
  93. cout << words[i];
  94. for (j = ; j < len; j++)
  95. printf(" ");
  96. if (i - start + > left)
  97. printf(" ");
  98. }
  99. cout << words[end - ] << endl;
  100. }
  101.  
  102. void output()
  103. {
  104. int i, best = , besti;
  105.  
  106. for (i = ; i <= wordsnum; i++)
  107. if (f[i][wordsnum] < best && f[i][wordsnum] >= )
  108. {
  109. best = f[i][wordsnum];
  110. besti = i;
  111. }
  112. int line[maxn];
  113. int j = wordsnum;
  114. for (i = besti; i > ; i--)
  115. {
  116. line[i] = from[i][j];
  117. j -= from[i][j];
  118. }
  119. j = ;
  120. for (i = ; i <= besti; i++)
  121. {
  122. printline(j, j + line[i]);
  123. j += line[i];
  124. }
  125. cout << endl;
  126. }
  127.  
  128. int main()
  129. {
  130. //freopen("D:\\t.txt", "r", stdin);
  131. while (cin >> n && n != )
  132. {
  133. init();
  134. work();
  135. output();
  136. }
  137. return ;
  138. }

poj1093的更多相关文章

  1. DP50题(转)

    转自https://www.luogu.org/blog/cccx2016/dp50-ti-ti-hao dp50题: poj1014 poj1015 poj1018 poj1036 poj1038 ...

随机推荐

  1. HDU 2028 Lowest Common Multiple Plus

    http://acm.hdu.edu.cn/showproblem.php?pid=2028 Problem Description 求n个数的最小公倍数.   Input 输入包含多个测试实例,每个 ...

  2. VSCODE 使用gitlab 推送代码的简单总结

    1. 前提条件: 有一个gitlab 服务器 自己的windows机器上面已经形成了 ssh key 以及进行了 gitlab global config 的配置 能够正常联系gitlab数据库 2. ...

  3. day5——Java 实现导出excel表 POI(转)

    1.首先下载poi-3.6-20091214.jar,下载地址如下: http://download.csdn.net/detail/evangel_z/3895051 2.Student.java ...

  4. DELPHI动态创建窗体

    //第一种方式 procedure TForm1.btn1Click(Sender: TObject); begin With TForm2.Create(Application) do Try Sh ...

  5. python自动化之调试

    #####调试 #####查看日志与断言 ''' 抛出异常使用raise语句.在代码中,raise语句包含以下部分: (1)raise关键字; (2)对Exception函数的调用; (3)传递给Ex ...

  6. 想转C++了

    暑假想学一学C++ 早退役了高考后才转C++的oier——我真是太蒻了

  7. 函数、可变参数、keyword-only参数、实参解构

    函数的数学定义:y=f(x) ,y是x的函数,x是自变量.y=f(x0, x1, ..., xn) python中的函数: 由函数名称.参数列表.和若干语句组成的语句块构成,完成一定的功能,是组织代码 ...

  8. Redis的持久化数据

    Redis支持两种持久化:RDB和AOF模式 一.名词解释: RDB:持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot).AOF:持久化记录服务器执行的 ...

  9. Access与SQL Server 语法差异

    序号 简述 Access语法 SqlServer语法 Oracle语法 解决方案 01 系统时间 Now(),Date() GETDATE() SYSDATE GetSysTimeStr 02 连接字 ...

  10. 使用 EXISTS 代替 IN 和 inner join

    在使用Exists时,如果能正确使用,有时会提高查询速度: 1,使用Exists代替inner join 2,使用Exists代替 in 1,使用Exists代替inner join例子: 在一般写s ...