列表

详情


NC51206. 诗人小G

描述

小G是一个出色的诗人,经常作诗自娱自乐。

但是,他一直被一件事情所困扰,那就是诗的排版问题。

一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中,注意一行中可以放的句子数目是没有限制的。

小G给每首诗定义了一个行标准长度(行的长度为一行中符号的总个数),他希望排版后每行的长度都和行标准长度相差不远。

显然排版时,不应改变原有的句子顺序,并且小G不允许把一个句子分在两行或者更多的行内。

在满足上面两个条件的情况下,小G对于排版中的每行定义了一个不协调度,为这行的实际长度与行标准长度差值绝对值的P次方,而一个排版的不协调度为所有行不协调度的总和。

小G最近又作了几首诗,现在请你对这几首诗进行排版,使得排版后的诗尽量协调(即不协调度尽量小),并把排版的结果告诉他。

输入描述

第一行包含一个整数T,表示诗的数量,接下来是T首诗,每首诗是一组数据。
每组数据的第一行包含三个整数N,L和P,其中N表示这首诗句子的数目,L表示这首诗的行标准长度,P的含义参考问题描述。
从第二行开始,每行一个句子,句子由英文字母、数字、标点符号等符号组成。

输出描述

对于每组数据,若最小的不协调度不超过,则输出一个数表示不协调度,若最小的不协调度超过1018,则输出”Too hard to arrange”(不包含引号),占一行。
每个输出后面加”--------------------“,占一行。

示例1

输入:

4
4 9 3
brysj,
hhrhl.
yqqlm,
gsycl.
4 9 2
brysj,
hhrhl.
yqqlm,
gsycl.
1 1005 6
poet
1 1004 6
poet

输出:

108
--------------------
32
--------------------
Too hard to arrange
--------------------
1000000000000000000
--------------------

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 165ms, 内存消耗: 3008K, 提交时间: 2022-08-12 13:00:44

#include <bits/stdc++.h>
#define M 100100
#define LIMIT 1000000000000000000ll
using namespace std;
typedef long double ld;
int n,l,p;
int sum[M],g[M],st[M],top;
ld f[M];
long double Slow_Power(long double x,int y)
{
    long double re=1;
    for(int i=1;i<=y;i++)
        re*=x;
    return re;
}
int Get_Len()
{
    static char s[40];
    scanf("%s",s+1);
    return strlen(s+1);
}
int Get_Pos(int x)
{
    int l=1,r=top;
    while(r-l>1)
    {
        int mid=l+r>>1;
        if( g[st[mid]]<=x )
            l=mid;
        else
            r=mid;
    }
    return g[st[r]]<=x?r:l;
}
ld F(int j,int i)
{
    return f[j]+Slow_Power(fabs(sum[i]-sum[j]+(i-j-1)-l),p);
}
int Get_G(int x,int y)
{
    int l=max(g[x],y)+1,r=n+1;
    while(r-l>1)
    {
        int mid=l+r>>1;
        if( F(y,mid) < F(x,mid) )
            r=mid;
        else
            l=mid;
    }
    if(l==r) return r;
    return F(y,l) < F(x,l) ? l : r ;
}
int main()
{
    int T,i;
    for(cin>>T;T;T--)
    {
        cin>>n>>l>>p;
        for(i=1;i<=n;i++)
            sum[i]=sum[i-1]+Get_Len();
        g[0]=1;st[top=1]=0;
        for(i=1;i<=n;i++)
        {
            int pos=st[Get_Pos(i)];
            f[i]=F(pos,i);
            while( g[st[top]]>i && F(i,g[st[top]]) < F(st[top],g[st[top]]) )
                st[top--]=0;
            pos=Get_G(st[top],i);
            if(pos!=n+1)
            {
                st[++top]=i;
                g[i]=pos;
            }
        }
        if(f[n]-0.5>LIMIT)
            puts("Too hard to arrange");
        else
            cout<<(long long)(f[n]+0.5)<<endl;
        puts("--------------------");
    }
    return 0;
}

C++ 解法, 执行用时: 503ms, 内存消耗: 6544K, 提交时间: 2022-02-02 14:27:46

#include<bits/stdc++.h>
#define cc(i,j) f[j]+qpow(abs(s[i]-s[j]-L))
using namespace std;
int n,L,P,s[100001],q[100001],k[100001],pr[100001],r,h,y,T,i,t;
long double f[100001];
char str[100001][33];
long double qpow(long double b){long double a=1;for(int k=P;k;k>>=1,b*=b)if(k&1)a*=b;return a;}
int bound(int x,int y){int l=x,r=n+1,m;while(l<r)m=(l+r)>>1,cc(m,x)>=cc(m,y)?r=m:l=m+1;return l;}
int main(){
	cin>>T;
    while(T--){
    	cin>>n>>L>>P;
    	L++;
        for(i=1;i<=n;++i){if(cin>>str[i]);s[i]=s[i-1]+strlen(str[i])+1;}
        for(q[i=h=t=1]=0;i<=n;++i){
            while(h<t&&k[h]<=i)++h;
            f[i]=cc(i,q[h]);
			pr[i]=q[h];
            while(h<t&&k[t-1]>=bound(q[t],i))t--;
            k[t]=bound(q[t],i);
			q[++t]=i;
        }
        if(f[n]>1e18)cout<<"Too hard to arrange\n";
        else{
            printf("%.0Lf\n",f[n]);
            for(q[t=0]=i=n;i;q[++t]=i=pr[i]);
        }
        cout<<"--------------------\n";
    }
    return 0;
}

上一题