# [BZOJ 1048] [HAOI2007] 分割矩阵 【记忆化搜索】

### 代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;

const int MaxN = 15 + 5, MaxT = 15 + 5;

int n, m, t, Num;
int Sum[MaxN][MaxN];

typedef double DB;

const DB INF = 999999999;

DB Ave;
DB f[MaxN][MaxN][MaxN][MaxN][MaxT];

DB Get(int x, int y, int xx, int yy) {
return (DB)(Sum[xx][yy] - Sum[x - 1][yy] - Sum[xx][y - 1] + Sum[x - 1][y - 1]);
}

inline DB Sqr(DB x) {return x * x;}
inline DB gmin(DB a, DB b) {return a < b ? a : b;}

DB Solve(int x, int xx, int y, int yy, int k) {
if (f[x][xx][y][yy][k] != -1) return f[x][xx][y][yy][k];
if (k == 1) return f[x][xx][y][yy][k] = Sqr(Get(x, y, xx, yy) - Ave);
DB ret = INF;
for (int i = x; i <= xx - 1; ++i)
for (int j = 1; j <= k - 1; ++j)
ret = gmin(ret, Solve(x, i, y, yy, j) + Solve(i + 1, xx, y, yy, k - j));
for (int i = y; i <= yy - 1; ++i)
for (int j = 1; j <= k - 1; ++j)
ret = gmin(ret, Solve(x, xx, y, i, j) + Solve(x, xx, i + 1, yy, k - j));
return f[x][xx][y][yy][k] = ret;
}

int main()
{
scanf("%d%d%d", &n, &m, &t);
for (int i = 1; i <= n; ++i)
for (int j = i; j <= n; ++j)
for (int p = 1; p <= m; ++p)
for (int q = p; q <= m; ++q)
for (int o = 1; o <= t; ++o)
f[i][j][p][q][o] = -1;
memset(Sum, 0, sizeof(Sum));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &Num);
Sum[i][j] = Sum[i][j - 1] + Sum[i - 1][j] - Sum[i - 1][j - 1] + Num;
}
}
Ave = (DB)Sum[n][m] / (DB)t;
Solve(1, n, 1, m, t);
printf("%.2lf\n", sqrt(f[1][n][1][m][t] / t));
return 0;
}


posted @ 2015-01-31 11:33  JoeFan  阅读(323)  评论(0编辑  收藏  举报