题意:每行限制宽度为m,然后给出n个单词的长度,将它们排版,每行不得超过m。最后对于每一行,如果不满m,则会有(m-len)^2的惩罚,求最小惩罚。(每两个单词之间会有一个空格,每行最后一个单词没有空格)
题解:dp[i]代表将前i个单词排好所花费的代价,sum[i]代表前i个单词的总长度,那么dp[i]=min(dp[j]+(m-(sum[i]-sum[j]+i-j-1))),j<i且满足sum[i]-sum[j]+i-j-1<=m,由于m<=100,所以nm的复杂度还是可以接受的。

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const long long inf=1ll<<62; 6 typedef long long LL; 7 LL dp[10005]; 8 LL sum[10005],a[10005]; 9 inline LL cal(LL x) 10 { 11 return x*x; 12 } 13 int main() 14 { 15 int T; 16 for(scanf("%d",&T);T;T--) 17 { 18 LL n,m; 19 scanf("%lld%lld",&m,&n); 20 dp[0]=sum[0]=0; 21 for(int i=1;i<=n;i++) 22 { 23 scanf("%lld",&a[i]); 24 sum[i]=sum[i-1]+a[i]; 25 } 26 for(int i=1;i<=n;i++) 27 { 28 LL val=inf; 29 for(int j=i-1;j>=0;j--) 30 { 31 if(sum[i]-sum[j]+i-j-1<=m) 32 val=min(val,dp[j]+cal(m-sum[i]+sum[j]-i+j+1)); 33 else 34 break; 35 } 36 dp[i]=val; 37 } 38 printf("%lld\n",dp[n]); 39 } 40 return 0; 41 }