题目
题解
题目的意思就是要最小化方差,就是要波动最小。
先来解释一下,最后的答案为什么是整数
设
s=∑ki=1xi
那么
x
=
sk
a2=k2∗∑ki=1x2i−2∗xi∗sk+s2k2k
拆开这个式子:
a2=k∗(∑ki=1x2i)−(∑ki=1xi)2
数据中,
∑ki=1xi
很小,可以将它设进dp的状态里面。
设
fi,j,k
表示当前的位置是(i,j),选择x的和是k时的最小的
∑ki=1x2i
转移就很简单了。
code
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define N 53
using namespace std;
int n,m,f[N][N][5000],h[N][N],ans;
char ch;
void read(int& n)
{
n=0;
for(ch=getchar();ch<'0' || ch>'9';ch=getchar());
for(;'0'<=ch && ch<='9';n=(n<<3)+(n<<1)+ch-48,ch=getchar());
}
int main()
{
freopen("route.in","r",stdin);
freopen("route.out","w",stdout);
read(n);read(m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
read(h[i][j]);
memset(f,127,sizeof(f));
f[0][1][0]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=h[i][j];k<=4950;k++)
{
f[i][j][k]=min(f[i-1][j][k-h[i][j]],f[i][j-1][k-h[i][j]]);
if(f[i][j][k]<250000)f[i][j][k]+=h[i][j]*h[i][j];
}
ans=2147483647;
for(int i=0;i<=4950;i++)
if(f[n][m][i]<250000)ans=min(ans,f[n][m][i]*(n+m-1)-i*i);
printf("%d",ans);
return 0;
}