棋盘分割

Description

将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。现在需要把棋盘按上述规则分割成n块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差,其中平均值,xi为第i块矩形棋盘的总分。
请编程对给出的棋盘及n,求出O'的最小值。

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

//输出要注意精度,一定使用long double
   1:  #include <cstdio>
   2:  #include <cmath>
   3:  #include <cstdlib>
   4:  #define min(a,b) a < b ? a : b
   5:  #define sqr(a) a*a
   6:  #define oo 214748364
   7:  int n;
   8:  int a[10][10];
   9:  int f[16][10][10][10][10];
  10:  int sum[10][10];
  11:  long double ave,tot;
  12:  int cal(int x1,int y1,int x2,int y2){
  13:      return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
  14:  }
  15:  int main(){
  16:      scanf("%d\n",&n);
  17:      for (int i=1;i<=8;i++){
  18:          for (int j=1;j<=8;j++){
  19:              scanf("%d",&a[i][j]);
  20:              tot+=a[i][j];
  21:              sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j];
  22:          }
  23:          scanf("\n");
  24:      }
  25:      ave=tot/n;
  26:      for (int x1=1;x1<9;x1++){
  27:          for (int y1=1;y1<9;y1++){
  28:                  for (int x2=x1;x2<9;x2++){
  29:                      for (int y2=y1;y2<9;y2++){
  30:                          f[1][x1][y1][x2][y2]=sqr(cal(x1,y1,x2,y2));
  31:                      }
  32:                  }
  33:          }
  34:      }
  35:      for (int i=2;i<=n;i++){
  36:          for (int x1=1;x1<9;x1++){
  37:              for (int y1=1;y1<9;y1++){
  38:                  for (int x2=x1;x2<9;x2++){
  39:                      for (int y2=y1;y2<9;y2++){
  40:                          f[i][x1][y1][x2][y2]=oo;
  41:                          for (int j=x1;j<x2;j++){
  42:                              int t=min(f[i-1][j+1][y1][x2][y2]+sqr(cal(x1,y1,j,y2)),f[i-1][x1][y1][j][y2]+sqr(cal(j+1,y1,x2,y2)));
  43:                              f[i][x1][y1][x2][y2]=min(t,f[i][x1][y1][x2][y2]);
  44:                          }
  45:                          for (int j=y1;j<y2;j++){
  46:                              int t=min(f[i-1][x1][j+1][x2][y2]+sqr(cal(x1,y1,x2,j)),f[i-1][x1][y1][x2][j]+sqr(cal(x1,j+1,x2,y2)));
  47:                              f[i][x1][y1][x2][y2]=min(t,f[i][x1][y1][x2][y2]);
  48:                          }
  49:                      }
  50:                  }
  51:              }
  52:          }
  53:      }
  54:      long double ans=sqrt((long double)f[n][1][1][8][8]/(long double)n-ave*ave);
  55:      printf("%.3lf\n",ans);
  56:      return 0;
  57:  }
  58: