【BZOJ1048】 [HAOI2007]分割矩阵

【BZOJ1048】[HAOI2007]分割矩阵

题面

bzoj

洛谷

题解

\(dp[a][b][c][d][num]\)表示将矩形\((a,b,c,d)\)分成\(num\)个的最小方差,然后转移即可

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include <vector> 
using namespace std;
#define sqr(x) ((x) * (x)) 
int A, B, N, a[15][15], s[15][15]; 
double ave, dp[15][15][15][15][15]; 
int sum(int x, int y, int _x, int _y) { return s[_x][_y] - s[_x][y - 1] - s[x - 1][_y] + s[x - 1][y - 1]; } 
double dfs(int x, int y, int _x, int _y, int num) { 
    if (dp[x][y][_x][_y][num] != 0) return dp[x][y][_x][_y][num]; 
    else if (num == 1) return 1.0 * sqr(sum(x, y, _x, _y) - ave);
    dp[x][y][_x][_y][num] = 1e9; 
    for (int i = y; i < _y; i++) {
        for (int j = 1; j < num; j++) {
            double res1 = dfs(x, y, _x, i, j) + dfs(x, i + 1, _x, _y, num - j); 
            double res2 = dfs(x, i + 1, _x, _y, j) + dfs(x, y, _x, i, num - j); 
            dp[x][y][_x][_y][num] = min(dp[x][y][_x][_y][num], min(res1, res2)); 
        } 
    } 
    for (int i = x; i < _x; i++) {
        for (int j = 1; j < num; j++) {
            double res1 = dfs(x, y, i, _y, j) + dfs(i + 1, y, _x, _y, num - j); 
            double res2 = dfs(i + 1, y, _x, _y, j) + dfs(x, y, i, _y, num - j);
            dp[x][y][_x][_y][num] = min(dp[x][y][_x][_y][num], min(res1, res2)); 
        } 
    }
    return dp[x][y][_x][_y][num]; 
} 
int main () {
    cin >> A >> B >> N; 
    for (int i = 1; i <= A; i++)
        for (int j = 1; j <= B; j++) cin >> a[i][j]; 
    for (int i = 1; i <= A; i++)
        for (int j = 1; j <= B; j++)
            s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j]; 
    ave = 1.0 * s[A][B] / N; 
    printf("%0.2lf\n", sqrt(dfs(1, 1, A, B, N) / N)); 
    return 0; 
} 
posted @ 2018-12-26 11:56  heyujun  阅读(...)  评论(... 编辑 收藏