poj1093
题意:给出一个句子和要求整理后每行包含的字符数,要求将其整理为一种总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数组可以求出最佳方案,然后按照题中要求输出即可。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std; const int maxn = ; int n, wordsnum;
string words[maxn];
int sum[maxn];
int f[maxn][maxn];
int from[maxn][maxn]; void turntowords(string st)
{
int i = ; while ()
{
i = ;
while (st[i] != ' ' && i < signed(st.length()))
i++;
words[wordsnum++] = st.substr(, i);
sum[wordsnum] = i + sum[wordsnum - ];
if (i == signed(st.length()))
break;
st.erase(, i);
while (st[] == ' ')
st.erase(, );
}
} void init()
{
string st; wordsnum = ;
memset(sum, , sizeof(sum));
getchar();
while ()
{
getline(cin, st);
if (st == "")
break;
turntowords(st);
}
} int cost(int start, int end)
{
int left, right, tot, len; if (end - start == )
return ;
tot = n - (sum[end] - sum[start]);
len = tot / (end - start - );
left = end - start - - tot % (end - start - );
right = tot % (end - start - );
return left * (len - ) * (len - ) + right * len * len;
} void work()
{
int i, j, k; memset(f, -, sizeof(f));
f[][] = ;
for (i = ; i <= wordsnum; i++)
for (j = ; j <= wordsnum; j++)
for (k = ; k <= j && j - k >= i - && n - (sum[j] - sum[j - k]) >= k - ; k++)
if (f[i - ][j - k] != - && (f[i][j] > f[i - ][j - k] + cost(j - k, j) || f[i][j] == -))
{
f[i][j] = f[i - ][j - k] + cost(j - k, j);
from[i][j] = k;
}
} void printline(int start, int end)
{
int left, tot, len, i, j; if (end - start == )
{
cout << words[start] << endl;
return;
}
tot = n - (sum[end] - sum[start]);
len = tot / (end - start - );
left = end - start - - tot % (end - start - );
for (i = start; i < end - ; i++)
{
cout << words[i];
for (j = ; j < len; j++)
printf(" ");
if (i - start + > left)
printf(" ");
}
cout << words[end - ] << endl;
} void output()
{
int i, best = , besti; for (i = ; i <= wordsnum; i++)
if (f[i][wordsnum] < best && f[i][wordsnum] >= )
{
best = f[i][wordsnum];
besti = i;
}
int line[maxn];
int j = wordsnum;
for (i = besti; i > ; i--)
{
line[i] = from[i][j];
j -= from[i][j];
}
j = ;
for (i = ; i <= besti; i++)
{
printline(j, j + line[i]);
j += line[i];
}
cout << endl;
} int main()
{
//freopen("D:\\t.txt", "r", stdin);
while (cin >> n && n != )
{
init();
work();
output();
}
return ;
}
poj1093的更多相关文章
- DP50题(转)
转自https://www.luogu.org/blog/cccx2016/dp50-ti-ti-hao dp50题: poj1014 poj1015 poj1018 poj1036 poj1038 ...
随机推荐
- java 封装,继承,多态基础
什么是封装? 1,对象数据和在.操作该对象的指令都是对象自身的一部分,能够实现尽可能对外部隐藏数据. 2,实际项目开发中,使用封装最多的就是实体类. 什么是继承? 1,继承是面向对象程序设计能提高效率 ...
- [转帖]Windows 内置端口转发功能
如何在Windows中使用netsh命令进行端口转发 https://www.freebuf.com/articles/system/176889.html 早上自己做了下实验,的确可以.linux下 ...
- 浅谈|WEB 服务器 -- Caddy
浅谈|WEB 服务器 -- Caddy 2018年03月28日 12:38:00 yori_chen 阅读数:1490 标签: caddyserverwebhttps反向代理 更多 个人分类: ser ...
- 【转帖】 redis 命令 From https://www.cnblogs.com/zhouweidong/p/7550717.html
redis命令详解 redis中添加key value元素:set key value; 获取元素:get key ; redis中添加集合:lpush key value1 va ...
- MySQL存储引擎 - Myisam和Innodb
Mysql有两种存储引擎:InnoDB与Myisam,下表是两种引擎的简单对比 MyISAM InnoDB 构成上的区别: 每个MyISAM在磁盘上存储成三个文件.第一个 文件的名字以表的名字开始 ...
- JS发送跨域Post请求出现两次请求的解决办法
原文地址: http://www.cnblogs.com/JimmyBright/p/7681097.html 所有跨域的js在提交post请求的时候,如果服务端设置了可跨域访问 public sta ...
- 【BZOJ1297】[SCOI2009]迷路(矩阵快速幂)
[BZOJ1297][SCOI2009]迷路(矩阵快速幂) 题面 BZOJ 洛谷 题解 因为边权最大为\(9\),所以记录往前记录\(9\)个单位时间前的.到达每个点的方案数就好了,那么矩阵大小就是\ ...
- AtCoder Grand Contest 006
AtCoder Grand Contest 006 吐槽 这套题要改个名字,叫神仙结论题大赛 A - Prefix and Suffix 翻译 给定两个串,求满足前缀是\(S\),后缀是\(T\),并 ...
- luogu1328 [NOIp2014]生活大爆炸版石头剪刀布 (模拟)
#include<bits/stdc++.h> #define pa pair<int,int> #define CLR(a,x) memset(a,x,sizeof(a)) ...
- AngularJS学习笔记3——AngularJS的工作原理
个人觉得,要很好的理解AngularJS的运行机制,才能尽可能避免掉到坑里面去.在这篇文章中,我将根据网上的资料和自己的理解对AngularJS的在启动后,每一步都做了些什么,做一个比较清楚详细的解析 ...