POJ 1093 Formatting Text

最长上升子序列类动态规划

dp[i] = min(dp[i],dp[j] + k)

题意:给定若干单词,把它们排成每行字符数为n的若干行,词与词之间可填充任意个空格,设某个单词与单词之间的空格数为g,(g-1)^2称为坏点,

  求使所有坏点和最小得排版方式.


技巧:因为要构造字母序最小的最优解,所以可以从后往前进行DP计算

View Code
#include<cstdio>
#include<cstring>
#define MAXN 10010
using namespace std;

char word[MAXN][82];
int a[MAXN],aft[MAXN],b[MAXN],m,n;

void Blank(int k)
{
    for(;k--;)
        putchar(' ');
}

int Cal(int i, int j)
{
    int g,t,k,ret;
    if(j==i+1)
        return 500;
    t=n-(a[i]-a[j]);
    k=j-i-1;
    g=t/k;
    ret=k*g*g+(t%k)*(2*g+1);
    return ret;
}

void Input()
{
    int i,j,k;
    char s[100];
    gets(s);
    for(k=0;gets(s),s[0]!='\0';)
        for(i=0;s[i]!='\0'&&s[i]!='\n';)
        {
            while(s[i]==' ')
                i++;
            if(s[i]=='\0'||s[i]=='\n')
                break;
            for(j=0;s[i]!='\0'&&s[i]!='\n'&&s[i]!=' ';j++,i++)
                word[k][j]=s[i];
            word[k++][j]='\0';
        }
    m=k;
    n++;
    a[m]=0;
    for(i=m-1;i>=0;i--)
        a[i]=(int)strlen(word[i])+1+a[i+1];
}

void Solve()
{
    int i,j,k;
    b[m]=0;
    for(i=m-1;i>=0;i--)
    {
        b[i]=b[i+1]+500;
        aft[i]=i+1;
        for(j=i+2;j<=m&&a[i]-a[j]<=n;j++)
        {
            k=Cal(i,j);
            if(b[i]>b[j]+k||(b[i]==b[j]+k&&Cal(i,j)<Cal(i,aft[i])))
                b[i]=b[j]+k,aft[i]=j;    
        }
    }
}

void Print()
{
    int k,t,g,d,i,j;
    for(i=0;i<m;i=j)
    {
        j=aft[i];
        if(j==i+1)
        {
            printf("%s",word[i]);
            putchar('\n');
        }
        else
        {
            t=n-(a[i]-a[j]);
            k=j-i-1;
            g=t/k;
            d=k-(t%k);
            for(;d--;i++)
            {
                printf("%s ",word[i]);
                Blank(g);
            }
            for(;i+1<j;i++)
            {
                printf("%s  ",word[i]);
                Blank(g);
            }
            puts(word[i]);
        }
    }
}

int main()
{
    for(;scanf("%d",&n),n;)
    {
        Input();
        Solve();
        Print();
        putchar('\n');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xchaos/p/2484751.html