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 }