POJ 1191 棋盘分割(记忆化搜索)

题意:

现在需要把棋盘分割成 n 块矩形棋盘,并使各矩形棋盘总分的均方差最小。

思路:

化简公式,记忆化搜索。

 

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

const int INFS = 0x3FFFFFFF;
int square[10][10][10][10], grid[10][10];
int dp[10][10][10][10][16];

void initsquare() {
    for (int i = 1; i <= 8; i++) {
        for (int j = 1; j <= 8; j++) {
            for (int p = i; p <= 8; p++) {
                for (int q = j; q <= 8; q++) {
                    int t = 0;
                    for (int x = i; x <= p; x++)
                        for (int y = j; y <= q; y++)
                            t += grid[x][y];
                    square[i][j][p][q] = t * t;
                }
            }
        }
    }
}

int solvedp(int k, int x, int y, int ex, int ey) {
    if (k == 1)
        return square[x][y][ex][ey];

    if (dp[x][y][ex][ey][k] != -1)
        return dp[x][y][ex][ey][k];

    int ans = INFS;
    for (int i = x; i < ex; i++) {
        ans = min(ans, square[x][y][i][ey] + solvedp(k-1, i+1, y, ex, ey));
        ans = min(ans, square[i+1][y][ex][ey] + solvedp(k-1, x, y, i, ey));
    } 
    for (int i = y; i < ey; i++) {
        ans = min(ans, square[x][y][ex][i] + solvedp(k-1, x, i+1, ex, ey));
        ans = min(ans, square[x][i+1][ex][ey] + solvedp(k-1, x, y, ex, i));
    }
    return dp[x][y][ex][ey][k] = ans;
}

int main() {
    int n;
    scanf("%d", &n);

    double ave = 0;
    for (int i = 1; i <= 8; i++) {
        for (int j = 1; j <= 8; j++) {
            scanf("%d", &grid[i][j]);
            ave += grid[i][j];
        }
    }
    initsquare();
    memset(dp, -1, sizeof(dp));
    double ans = solvedp(n, 1, 1, 8, 8);
    ave /= n;
    ans /= n;
    ans -= ave * ave;
    printf("%.3lf\n", sqrt(ans));
    return 0;
}
posted @ 2013-04-02 16:53  kedebug  阅读(235)  评论(0编辑  收藏  举报