HDU 2517 棋盘分割(DP)

来源:互联网 发布:数据库管理软件 编辑:程序博客网 时间:2024/05/29 15:22

思路:dp[n][x1][y1][x2][y2],表示还剩n刀可以切,当前矩形位置为左上角(x1,y1), 右下角(x2,y2),

然后把公式转化下,其实就是求平方和最小


代码:

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int N = 10;const double INF = 1e18;int n, vis[15][N][N][N][N];double num[N][N], sum[N][N], dp[15][N][N][N][N];double get(int x1, int y1, int x2, int y2) {double tmp = sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];tmp *= tmp;return tmp;}double dfs(int n, int x1, int y1, int x2, int y2) {if (vis[n][x1][y1][x2][y2]) return dp[n][x1][y1][x2][y2];vis[n][x1][y1][x2][y2] = 1;double &ans = dp[n][x1][y1][x2][y2];ans = INF;if (n == 1) return ans = get(x1, y1, x2, y2);for (int i = x1; i < x2; i++) {ans = min(ans, dfs(n - 1, i + 1, y1, x2, y2) + get(x1, y1, i, y2));ans = min(ans, dfs(n - 1, x1, y1, i, y2) + get(i + 1, y1, x2, y2));}for (int i = y1; i < y2; i++) {ans = min(ans, dfs(n - 1, x1, i + 1, x2, y2) + get(x1, y1, x2, i));ans = min(ans, dfs(n - 1, x1, y1, x2, i) + get(x1, i + 1, x2, y2));}return ans;}int main() {while (~scanf("%d", &n)) {for (int i = 1; i <= 8; i++)for (int j = 1; j <= 8; j++) {scanf("%lf", &num[i][j]);sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + num[i][j];}memset(vis, 0, sizeof(vis));printf("%.3lf\n", sqrt(dfs(n, 1, 1, 8, 8) / n - (sum[8][8] * sum[8][8] / n / n))); }return 0;}


0 0