题目大意:给n,然后在给出一篇文章,有若干个单词,以空行结束,现在要将文章排序使得文章的badness 越小。
badness 的计算方法,如果一行只有一个单词的话,若单词的长度小于n,则badness 增加500,否则为0。
若一行有多个单词,每两个单词之间的badness = (c - 1) ^ 2 (c为两个单词的空格数),要求,每行控制长度在n,并且头一个单词顶头,最后后一个单词顶尾,头疼的一题,又是一晚上,看了题解 ,,细节很重要,DP每一个单词最佳的放置位置,详细看题解,
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
char s[10005],words[10005][85];
int n,top,len[10005],dp[10005][85];
int DP(int i,int j)
{
if(dp[i][j] != -1)
return dp[i][j];
dp[i][j] = INF;
if(i == top){
if(j == 0)
return dp[i][j] = 0;
else
return dp[i][j];
}
//单独一行
if(j == 0)
dp[i][j] = min(dp[i][j],(len[i]<n?500:0)+DP(i+1,0));
//行尾
if(j+len[i] == n)
return dp[i][j] = min(dp[i][j],DP(i+1,0));
//行中
else{
//下一个单词可放位置
int x=j+len[i]+1;
for(int k = x; k < n; k++)
{
//此行k位置放不下下一个单词
if(k + len[i+1] > n)
break;
int t = k - x;
dp[i][j] = min(dp[i][j],t*t+DP(i+1,k));
}
}
return dp[i][j];
}
void print(int i,int j)
{
if(i == top)
{
puts("");
return;
}
printf("%s",words[i]);
if(j == 0 && dp[i][j] == dp[i+1][0]+(len[i]<n?500:0)){
puts("");
print(i+1,0);
}
else if(j+len[i] == n && dp[i][j] == dp[i+1][0]){
puts("");
print(i+1,0);
}
else{
//下一个单词可放位置
int x=j+len[i]+1;
for(int k = x; k < n; k++)
{
//此行k位置放不下下一个单词
if(k+len[i+1]>n)
break;
int t = k-x;
if(dp[i][j] == t*t+dp[i+1][k])
{
for(int l = 0; l <= t; l++)
putchar(' ');
print(i+1,k);
break;
}
}
}
}
int main(){
while(scanf("%d",&n),n){
getchar();
top = 0;
while(gets(s)){
if(!s[0])
break;
int i = 0;
for(;s[i]==' ';i++);
for(;s[i];){
sscanf(s+i,"%s",words[top]);
for(; s[i]!=' '&&s[i]; i++);
for(; s[i]==' '; i++);
len[top] = strlen(words[top]);
top++;
}
}
len[top]=0;
memset(dp,-1,sizeof(dp));
DP(0,0);
print(0,0);
}
return 0;
}