Description
Input
第1行为一个整数n(1 <= n <= 15 )
第2行至第9行每行为8个小于100的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。
Output
仅一个数,为O'(四舍五入精确到小数点后三位)。
Sample Input
3
1 1 1 1 1 1 1 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0
1 1 1 1 1 1 0 3
Sample Output
1.633
Source
题目:EOJ1096
题目分析:
均方差用方差的根号表示,方差最小时,均方差最小,化简可得方差公式为∑Xi^2/n-x^2,即求Xi平方和的最小值。可以用递归的思想求解,将一个矩形分为k个,枚举出所有将此矩形分成两部分的方法,再将这两部分矩形中,其中一个分成一个(既不用再分),将另一个矩形分为k-1个。为提高效率,采用记忆化搜索。用dp(x1,y1.x2,y2,k)表示将左上角和右下角坐标分别为(x1,y1),(x2,y2)的一个矩形分为k块的Xi的平方和的最小值。注意当x1=x2时表示矩形长度为1,y1=y2时同理。
AC代码:
#include<iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
int dp[9][9][9][9][16];
int map[10][10]={};
int f(int x1,int y1,int x2,int y2,int k)
{
if(dp[x1][y1][x2][y2][k]>=0 || k==1 || (x2==x1 && y2==y1))
returndp[x1][y1][x2][y2][k];
int i;
intans1=210000000,ans2=2100000000;
for(i=x1;i<x2;++i)
{
ans1=min(ans1,min(dp[x1][y1][i][y2][1]+f(i+1,y1,x2,y2,k-1),
f(x1,y1,i,y2,k-1)+dp[i+1][y1][x2][y2][1] ));
}
for(i=y1;i<y2;++i)
{
ans2=min(ans2,min(dp[x1][y1][x2][i][1]+f(x1,i+1,x2,y2,k-1),
f(x1,y1,x2,i,k-1)+dp[x1][i+1][x2][y2][1]));
}
dp[x1][y1][x2][y2][k]=min(ans1,ans2);
return dp[x1][y1][x2][y2][k];
}
int main()
{
int n,all=0;
cin>>n;
int i,j,x1,x2,y1,y2;
for(i=1;i<9;++i)
for(j=1;j<9;++j)
{
cin>>map[i][j];
all+=map[i][j];
}
memset(dp,-1,sizeof(dp));
for(x1=1;x1<9;++x1)
for(x2=x1;x2<9;++x2)
for(y1=1;y1<9;++y1)
for(y2=y1;y2<9;++y2)
{
int t=0;
for(i=x1;i<=x2;++i)
for(j=y1;j<=y2;++j)
t+=map[i][j];
dp[x1][y1][x2][y2][1]=t*t;
}
doublea=1.0*f(1,1,8,8,n),b=1.0*all/n;
//printf("%f %f\n",a,b);
printf("%.3f\n",sqrt( a/n-b*b ));
return 0;
}