参照了黑书上的思路,先对方差进行化简,变为求矩阵的平方和最大,然后动态规划。
用G++一直WA,改用C++就过了,百度了下发现G++输出double要用%f。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int dp[17][9][9][9][9];
int A[9][9];
int sum[9][9][9][9];
const int maxn=1000000000;
int main()
{
int n,i,j,k,l,x,y,a;
double ssum=0;
scanf("%d",&n);
for (i=1;i<=8;i++)
for (j=1;j<=8;j++)
{
scanf("%d",&A[i][j]);
ssum+=A[i][j];
}
for (i=1;i<=8;i++)
for (j=1;j<=8;j++)
{
for (k=i;k<=8;k++)
for (l=j;l<=8;l++)
{
for (x=i;x<=k;x++)
for (y=j;y<=l;y++)
sum[i][j][k][l]+=A[x][y];
sum[i][j][k][l]*=sum[i][j][k][l];
dp[1][i][j][k][l]=sum[i][j][k][l];
}
}
for (k=2;k<=n;k++)
{
for (i=1;i<=8;i++)
for (j=1;j<=8;j++)
for (x=i;x<=8;x++)
for (y=j;y<=8;y++)
{
dp[k][i][j][x][y]=maxn;
for (a=i;a<x;a++)
dp[k][i][j][x][y]=min( min(dp[k-1][a+1][j][x][y]+sum[i][j][a][y], dp[k-1][i][j][a][y]+sum[a+1][j][x][y]),dp[k][i][j][x][y] );
for (a=j;a<y;a++)
dp[k][i][j][x][y]=min( min(dp[k-1][i][a+1][x][y]+sum[i][j][x][a], dp[k-1][i][j][x][a]+sum[i][a+1][x][y]),dp[k][i][j][x][y] );
}
}
double aver=ssum/n;
printf("%.3lf\n",sqrt((double)dp[n][1][1][8][8]/n-aver*aver));
}