poj 1191 棋盘分割(dp + 记忆化搜索)

题目:http://poj.org/problem?id=1191

黑书116页的例题

将方差公式化简之后就是 每一块和的平方 相加/n , 减去平均值的平方。

可以看出来 方差只与 每一块的和的平方有关,所以就是求每个矩形的总分的平方和 尽量小。。。。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 using namespace std;
 8 const int INF = 1<<28;
 9 int sum[10][10], d[20][10][10][10][10];//sum存储从【1,1】到【i, j】的和
10 int _min(int a, int b)
11 {
12     return a>b?b:a;
13 }
14 int getsum(int x1, int y1, int x2, int y2) //计算从【x1,y1】到【x2, y2】的和。
15 {
16     return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
17 }
18 int slove(int k, int x1, int y1, int x2, int y2)
19 {
20     int s1, s2, Min, temp1, temp2;
21     int i;
22     if(d[k][x1][y1][x2][y2]!=-1) //不等于1表示已经求过了,不需要再求了
23     return d[k][x1][y1][x2][y2];
24     if(k == 1)  //表示已经切了n块了,不需要再切了
25     {
26         s1 = getsum(x1, y1, x2, y2);
27         return (d[k][x1][y1][x2][y2] = s1*s1);
28     }
29     Min = INF;
30     for(i = x1; i < x2; i++)  //横向切
31     {
32         s1 = getsum(x1, y1, i, y2);
33         s2 = getsum(i+1, y1, x2, y2);
34         temp1 = _min(slove(k-1, i+1, y1, x2, y2)+s1*s1, slove(k-1, x1, y1, i, y2)+s2*s2);
35         if(temp1 < Min)
36         Min = temp1;
37     }
38     for(i = y1; i < y2; i++) //纵向切
39     {
40         s1 = getsum(x1, y1, x2, i);
41         s2 = getsum(x1, i+1, x2, y2);
42         temp2 = _min(slove(k-1, x1, i+1, x2, y2)+s1*s1, slove(k-1, x1, y1, x2, i)+s2*s2);
43         if(temp2 < Min)
44         Min = temp2;
45     }
46     return (d[k][x1][y1][x2][y2] = Min);
47 }
48 int main()
49 {
50     int n, i, j, val, x;
51     double aver, var;
52     while(~scanf("%d", &n))
53     {
54         memset(d, -1, sizeof(d));
55         memset(sum, 0, sizeof(sum));
56         for(i = 1; i <= 8; i++)
57         for(j = 1, x = 0; j <= 8; j++)
58         {
59             scanf("%d", &val);
60             x += val;
61             sum[i][j] = sum[i-1][j] + x;
62         }
63         aver = sum[8][8]*1.0/n;  //所有块的平方和
64         int sum_t = slove(n, 1, 1, 8, 8);
65         var = sqrt(sum_t*1.0/n-aver*aver);
66 
67         printf("%.3lf\n", var);
68     }
69     return 0;
70 }

 

 

posted @ 2014-02-25 21:32  水门  阅读(172)  评论(0编辑  收藏  举报