这题动态规划,太难了,参考了别人的思路,写了这份报告。
分析一下,根据题意,要求均方差ans = sqrt(Sum((x[i]-x的平均值)^2)/n),ans^2=Sum(x[i]*x[i])/n-(x的平均值)^2,而x的平均值是固定值(即所有方格数字的和/n),所以只要使得切割后的矩形的总分的平方和尽量小,由于切割只能沿着棋盘的边进行,故对于左上角坐标为[x1,y1],右下角坐标[x2,y2]的棋盘,可以沿着横线切或者沿着竖线切,如用dp[n][x1][y1][x2][y2]表示将上述矩形切割为n个时的矩形的总分的最小平方和,则有在横向有状态转移方程:dp[n][x1][y1][x2][y2]
= Min((dp[n][x1][y1][i][y2]+sum(i+1,y1,x2,y2)))
代码如下
#include<stdio.h>
#include<math.h>
#define N 9
#define D 16
#define INF 9999999
int dp[D][N][N][N][N];
int s[N][N][N][N];
int a[N][N];
int n;
int Sum(int x1,int y1,int x2,int y2)
{
int ans=0;
int i,j;
if(s[x1][y1][x2][y2]>0)
return s[x1][y1][x2][y2];
for(i=x1;i<=x2;i++)
{
for(j=y1;j<=y2;j++)
ans+=a[i][j];
}
s[x1][y1][x2][y2]=ans*ans;
return s[x1][y1][x2][y2];
}
int Divide(int n,int x1,int y1,int x2,int y2)
{
int min,i,j,m;
if(n==1)
{
if(dp[n][x1][y1][x2][y2]==-1)
dp[n][x1][y1][x2][y2]=Sum(x1,y1,x2,y2);
return dp[n][x1][y1][x2][y2];
}
if(dp[n][x1][y1][x2][y2]!=-1)
return dp[n][x1][y1][x2][y2];
min=INF;
for(i=x1;i<x2;i++)
{
m=Divide(n-1,x1,y1,i,y2)+Sum(i+1,y1,x2,y2);
if(min>m)
min=m;
m=Divide(n-1,i+1,y1,x2,y2)+Sum(x1,y1,i,y2);
if(min>m)
min=m;
}
for(j=y1;j<y2;j++)
{
m=Divide(n-1,x1,y1,x2,j)+Sum(x1,j+1,x2,y2);
if(min>m)
min=m;
m=Divide(n-1,x1,j+1,x2,y2)+Sum(x1,y1,x2,j);
if(min>m)
min=m;
}
dp[n][x1][y1][x2][y2]=min;
return min;
}
void main()
{
int i,j;
double sum=0.0,ans;
scanf("%d",&n);
for(i=1;i<N;i++)
{
for(j=1;j<N;j++)
{
scanf("%d",&a[i][j]);
sum+=a[i][j];
}
}
sum/=n;
memset(dp,-1,sizeof(dp));
memset(s,0,sizeof(s));
ans=Divide(n,1,1,N-1,N-1);
ans=sqrt(ans/n-sum*sum);
printf("%.3lf\n",ans);
}