题意:给出一个句子和要求整理后每行包含的字符数,要求将其整理为一种总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的更多相关文章

  1. DP50题(转)

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

随机推荐

  1. ELK 性能(1) — Logstash 性能及其替代方案

    ELK 性能(1) - Logstash 性能及其替代方案 介绍 当谈及集中日志到 Elasticsearch 时,首先想到的日志传输(log shipper)就是 Logstash.开发者听说过它, ...

  2. python自动化之鼠标移动

    ################################用GUI自动化控制键盘和鼠标############################### ''' http://pyautogui.r ...

  3. ubuntu系统部署web项目

    1.安装java 下载java安装文件 可至http://www.oracle.com/technetwork/java/javase/downloads/index.html下载最新的JDK版本,当 ...

  4. MT【88】抽象函数

    分析:此类题一般有两种做法,第一种按解答题做法, 第二种作为填空题找对应的特殊函数,比如这里可以根据三角里和差化积得出$f(x)=\frac{1}{2}cos(\frac{\pi}{3}x)$

  5. KUR-Couriers

    题目链接: QwQ Solution: 以权值为下标,对每个点建树 对于x点,以它为根的树涵盖的是1到x区间内每个数出现的次数 Code: #include<bits/stdc++.h> ...

  6. BZOJ 3609: [Heoi2014]人人尽说江南好

    3609: [Heoi2014]人人尽说江南好 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 470  Solved: 336[Submit][Sta ...

  7. LJ 5月6日A组考试考试题解

    [题目] T1(L2837) 晚餐队列安排 [题面] 为了避免餐厅过分拥挤,FJ要求奶牛们分2批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想,所有第2批就餐的奶牛排在队尾,队伍的前半部分 ...

  8. hdu 1358 Period 最小循环节

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1358 分析:已知字符串,求其由最小循环节构成的前缀字符串. /*Period Time Limit: ...

  9. fidder及Charles使用

    1. fidder抓https包的基本配置,可参见以下博文 http://blog.csdn.net/idlear/article/details/50999490 2. 遇到问题:抓包看只有Tunn ...

  10. Nginx反向代理1--基本介绍-虚拟主机

    1   Nginx 1.1   什么是nginx Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.由俄罗斯的程序设计师Igor Sysoev所开发, ...