POJ 1191 棋盘分割(区间DP)题解

题意:中文题面

思路:不知道直接暴力枚举所有情况行不行。。。

我们可以把答案转化为

所以答案就是求xi2的最小值,那么我们可以直接用区间DP来写。设dp[x1][y1][x2][y2][k]为x1 y1 到 x2 y2 区间分割为k份的最下平方和,显然k = 1是就是区间和的平方。

写了6层for,写出来自己都不信。。。

交C++才过。。。

代码:

#include<cmath>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
int n;
double w[maxn][maxn], dp[maxn][maxn][maxn][maxn][maxn], sum[maxn][maxn];
double get(int x1, int y1, int x2, int y2){
    return sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1];
}
int main(){
    scanf("%d", &n);
    memset(sum, 0, sizeof(sum));
    for(int i = 1; i <= 8; i++){
        for(int j = 1; j <= 8; j++){
            scanf("%lf", &w[i][j]);
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + w[i][j];
        }
    }
    double per = sum[8][8] / n;
    for(int x1 = 1; x1 <= 8; x1++){
        for(int y1 = 1; y1 <= 8; y1++){
            for(int x2 = x1; x2 <= 8; x2++){
                for(int y2 = y1; y2 <= 8; y2++){
                    double ret = get(x1, y1, x2, y2);
                    dp[x1][y1][x2][y2][1] = ret * ret;
                }
            }
        }
    }
    for(int k = 2; k <= n; k++){
        for(int x1 = 1; x1 <= 8; x1++){
            for(int y1 = 1; y1 <= 8; y1++){
                for(int x2 = x1; x2 <= 8; x2++){
                    for(int y2 = y1; y2 <= 8; y2++){
                        dp[x1][y1][x2][y2][k] = INF;
                        for(int t = x1; t < x2; t++){
                            dp[x1][y1][x2][y2][k] = min(dp[x1][y1][x2][y2][k], dp[x1][y1][t][y2][1] + dp[t + 1][y1][x2][y2][k - 1]);
                            dp[x1][y1][x2][y2][k] = min(dp[x1][y1][x2][y2][k], dp[x1][y1][t][y2][k - 1] + dp[t + 1][y1][x2][y2][1]);
                        }
                        for(int t = y1; t < y2; t++){
                            dp[x1][y1][x2][y2][k] = min(dp[x1][y1][x2][y2][k], dp[x1][y1][x2][t][1] + dp[x1][t + 1][x2][y2][k - 1]);
                            dp[x1][y1][x2][y2][k] = min(dp[x1][y1][x2][y2][k], dp[x1][y1][x2][t][k - 1] + dp[x1][t + 1][x2][y2][1]);
                        }
                    }
                }
            }
        }
    }
    printf("%.3lf\n", sqrt(dp[1][1][8][8][n] / n - per * per));
    return 0;
}

 

posted @ 2019-04-01 21:00  KirinSB  阅读(167)  评论(0编辑  收藏  举报