POJ 1191 (DP)

View Code
  1 /*
  2 思路:
  3 我们可以对棋盘进行横向切割和竖向切割 
  4 s[n][x1][y2][x2][y2]表示:棋盘的左上角坐标是(x1,y1),右下角坐标
  5 为(x2,y2)  把这个棋盘分割成  n 一块
  6 横向分割:
  7 可以在 a处分割  (x1=<a<x2)  比较是 留哪一个继续分割 
  8 for(a=x1;a<x2;++a)
  9          {
 10            r=min(r,min(slove(num-1,x1,y1,a,y2)+sum(a+1,y1,x2,y2),//对上边递归继续分割 
 11                      slove(num-1,a+1,y1,x2,y2)+sum(x1,y1,a,y2)));//对下边递归继续分割
 12                      
 13 竖向分割:
 14 可以在  b 处分割  (y1=<b<y2) 比较是留哪一个
 15       for(b=y1;b<y2;++b)
 16          {
 17            r=min(r,min(slove(num-1,x1,y1,x2,b)+sum(x1,b+1,x2,y2),//对左边继续分割 
 18                      slove(num-1,x1,b+1,x2,y2)+sum(x1,y1,x2,b)));//对右边继续分割 
 19          }
 20 最后的均方差可以化简为:
 21 (x1^2 + x2^2 + ....+xn^2)/n-(xba)^2;
 22 
 23 
 24 rect[i][j]存放的是从(0,0)到 (i,j)这个矩形所有元素的和   
 25 
 26 注意:输出时 数学函数  pow(double ,double)   
 27 */
 28 #include<stdio.h>
 29 #include<math.h>
 30 #include<string.h>
 31 #define size 8
 32 #define min(a,b) ((a)<(b))?(a):(b)
 33 
 34 int s[15][size+1][size+1][size+1][size+1];
 35 int rect[size+1][size+1];
 36 int n;
 37 
 38 void inputs()
 39 {
 40   int i,j;
 41   scanf("%d",&n);
 42   for(i=1;i<=size;++i)
 43    for(j=1;j<=size;++j)
 44     scanf("%d",&rect[i][j]);
 45 }
 46 
 47 void initial()
 48 {
 49    int i,j;
 50    memset(s,-1,sizeof(s));
 51    for(i=0;i<=size;++i)
 52     rect[i][0]=rect[0][i]=0;
 53    for(i=1;i<=size;++i)
 54     for(j=1;j<=size;++j)
 55      rect[i][j]+=rect[i-1][j]+rect[i][j-1]-rect[i-1][j-1];
 56 }
 57 
 58 int sum(int x1,int y1,int x2,int y2)
 59 {
 60    int ret = rect[x2][y2]-rect[x1-1][y2]-rect[x2][y1-1]+rect[x1-1][y1-1];
 61    return ret*ret;
 62 }
 63 
 64 int slove(int num,int x1,int y1,int x2,int y2)
 65 {
 66    int a,b;
 67    int r=1000000000;
 68    if(s[num][x1][y1][x2][y2]!=-1)
 69      return s[num][x1][y1][x2][y2];
 70    else 
 71     {
 72       if(num==1 || x1==x2 || y1==y2)
 73       {
 74         s[num][x1][y1][x2][y2]=sum(x1,y1,x2,y2);
 75         return s[num][x1][y1][x2][y2];
 76       }
 77       else
 78       {
 79         for(a=x1;a<x2;++a)
 80          {
 81            r=min(r,min(slove(num-1,x1,y1,a,y2)+sum(a+1,y1,x2,y2),
 82                      slove(num-1,a+1,y1,x2,y2)+sum(x1,y1,a,y2)));
 83          }
 84         for(b=y1;b<y2;++b)
 85          {
 86            r=min(r,min(slove(num-1,x1,y1,x2,b)+sum(x1,b+1,x2,y2),
 87                      slove(num-1,x1,b+1,x2,y2)+sum(x1,y1,x2,b)));
 88          }
 89         s[num][x1][y1][x2][y2]=r;
 90         return r;
 91      }
 92    }
 93     
 94 }
 95 
 96 void print()
 97 {
 98    double res;
 99    res=sqrt((double)slove(n, 1, 1, size, size)/n-pow(sqrt((double)sum(1, 1, size, size))/n, 2.0));
100    printf("%.3f\n", res);
101 }
102 
103 int main()
104 {
105   inputs();
106   initial();
107   print();
108   scanf("%d",&n);
109   return 0;
110 }

 

posted @ 2012-04-14 12:20  知行执行  阅读(192)  评论(0编辑  收藏  举报