设g[i][j] 表示下面长度为i的一段放j个的最小花费。
那么g[i][j]=k2∗(i/j+1)2∗(i%j)+k2∗(i/j)2∗(j−i%j)
(使所有尽量相等时花费最小)
设f[i][j][k] 表示到i,上面有j个矩形,下面有k个矩形的最小花费。
然后转移时枚举上面的第j个的长度和下面对应上面第j个有多少个。
由于上面的顺序对答案没有影响,那么令上面的边长从左到右递减。
此时上面的第j个的长度只需要枚举到i/j 即可。
复杂度O(n4)
#include <bits/stdc++.h>
using namespace std;
#define N 110
int n,m;
double k1,k2;
double g1[N][N],g2[N],f[N][N][N];
int main()
{
//freopen("tt.in","r",stdin);
scanf("%lf%lf%d%d",&k1,&k2,&m,&n);
for(int i=1;i<=100;i++)
for(int j=1;j<=i&&j<=n;j++)
g1[i][j]=k2*(i/j+1)*(i/j+1)*(i%j)+k2*(i/j)*(i/j)*(j-i%j);
for(int i=1;i<=100;i++)
g2[i]=k1*i*i;
for(int i=0;i<=100;i++)
for(int j=0;j<=100;j++)
for(int k=0;k<=100;k++)
f[i][j][k]=1e100;
f[0][0][0]=0;
for(int i=1;i<=100;i++)
for(int j=1;j<=m&&j<=i;j++)
for(int k=j;k<=n&&k<=i;k++)
for(int t=1;t<=i/j;t++)
for(int w=1;w<=t&&w<=k;w++)
f[i][j][k]=min(f[i][j][k],f[i-t][j-1][k-w]+g1[t][w]+g2[t]);
printf("%.1lf\n",f[100][m][n]);
return 0;
}