# BZOJ 1048 分割矩阵

5 4 4
2 3 4 6
5 7 5 1
10 4 0 5
2 0 2 3
4 1 1 1

0.50

## Source

f[i][j][k][l][p]表示横坐标为i到j，纵坐标为k到l的矩阵分成p份对答案贡献的最小值。(即为分割成的p份的每份的矩阵权值和与平均数的差的平方的和。eg：假设p=2，两个矩阵的权值和分别为s1、s2，平均数为m，则f[i][j][k][l][p]=(s1-m)2+(s2-m)2)。暴搜随便枚举几下就可以了。

 1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<cstdlib>
5 #include<cmath>
6 using namespace std;
7
8 #define inf (1e18)
9 #define maxn 15
10 int A,B,N; double f[maxn][maxn][maxn][maxn][maxn],s[maxn][maxn],ave;
11
12 inline double qua(double a) { return a*a; }
13
14 inline double calc(int h1,int h2,int l1,int l2)
15 {
16     double ret = 0;
17     for (int i = h1;i <= h2;++i)
18         for (int j = l1;j <= l2;++j) ret += s[i][j];
19     return ret;
20 }
21
22 inline int size(int h1,int h2,int l1,int l2) { return (h2-h1+1)*(l2-l1+1); }
23
24 inline double dfs(int h1,int h2,int l1,int l2,int k)
25 {
26     if (f[h1][h2][l1][l2][k] >= 0) return f[h1][h2][l1][l2][k];
27     if (k == 1) return f[h1][h2][l1][l2][k] = qua(calc(h1,h2,l1,l2)-ave);
28     f[h1][h2][l1][l2][k] = 1e18;
29     for (int i = 1;i < k;++i)
30     {
31         for (int j = h1;j < h2;++j)
32             if (size(h1,j,l1,l2)>=i&&size(j+1,h2,l1,l2)>=k-i)
33                 f[h1][h2][l1][l2][k] = min(f[h1][h2][l1][l2][k],dfs(h1,j,l1,l2,i)+dfs(j+1,h2,l1,l2,k-i));
34         for (int j = l1;j < l2;++j)
35             if (size(h1,h2,l1,j)>=i&&size(h1,h2,j+1,l2)>=k-i)
36                 f[h1][h2][l1][l2][k] = min(f[h1][h2][l1][l2][k],dfs(h1,h2,l1,j,i)+dfs(h1,h2,j+1,l2,k-i));
37     }
38     return f[h1][h2][l1][l2][k];
39 }
40
41 int main()
42 {
43     scanf("%d %d %d",&A,&B,&N);
44     for (int i = 1;i <= A;++i)
45         for (int j = 1;j <= B;++j) scanf("%lf",s[i]+j);
46     memset(f,128,sizeof(f)); ave = calc(1,A,1,B)/(1.0*N);
47     dfs(1,A,1,B,N);
48     printf("%.2lf",sqrt(f[1][A][1][B][N]/(1.0*N)));
49     return 0;
50 }
View Code

posted @ 2015-02-16 14:36  lmxyy  阅读(261)  评论(0编辑  收藏  举报