zoukankan      html  css  js  c++  java
  • 洛谷P1436 棋盘分割 题解 二维区间DP

    题目链接:https://www.luogu.com.cn/problem/P1436

    这道题目和《算法艺术与信息学竞赛》的题目描述稍微有点区别(这里是求平方和的最小值,书上是方差的最小值),不过解法都是一样的,就是区间DP,我这里使用记忆化搜索实现。

    (f[r1][c1][r2][c2][m]) 表示以 ((r1,c1)) 为左上角的格子,以 ((r2,c2)) 为右下角的格子,并且分成 (m) 份的最小平方和。

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 10;
    int n, a[maxn][maxn], low[maxn][maxn], sum[maxn][maxn];
    int get_sum(int r1, int c1, int r2, int c2) {
        int t = sum[r2][c2] - sum[r1-1][c2] - sum[r2][c1-1] + sum[r1-1][c1-1];
        return t * t;
    }
    int f[maxn][maxn][maxn][maxn][15];
    bool vis[maxn][maxn][maxn][maxn][15];
    int solve(int r1, int c1, int r2, int c2, int m) {
        if (vis[r1][c1][r2][c2][m]) return f[r1][c1][r2][c2][m];
        vis[r1][c1][r2][c2][m] = true;
        if (m == 1) return f[r1][c1][r2][c2][m] = get_sum(r1, c1, r2, c2);
        if (r1 == r2 && c1 == c2) return f[r1][c1][r2][c2][m] = -1;
        int ans = -1;
        if (r1 < r2) {
            for (int i = r1; i < r2; i ++) {
                int tmp1 = solve(r1, c1, i, c2, 1);
                int tmp2 = solve(i+1, c1, r2, c2, m-1);
                if (tmp1 != -1 && tmp2 != -1) {
                    if (ans == -1 || ans > tmp1 + tmp2) {
                        ans = tmp1 + tmp2;
                    }
                }
            }
            for (int i = r1; i < r2; i ++) {
                int tmp1 = solve(r1, c1, i, c2, m-1);
                int tmp2 = solve(i+1, c1, r2, c2, 1);
                if (tmp1 != -1 && tmp2 != -1) {
                    if (ans == -1 || ans > tmp1 + tmp2) {
                        ans = tmp1 + tmp2;
                    }
                }
            }
        }
        if (c1 < c2) {
            for (int i = c1; i < c2; i ++) {
                int tmp1 = solve(r1, c1, r2, i, 1);
                int tmp2 = solve(r1, i+1, r2, c2, m-1);
                if (tmp1 != -1 && tmp2 != -1) {
                    if (ans == -1 || ans > tmp1 + tmp2) {
                        ans = tmp1 + tmp2;
                    }
                }
            }
            for (int i = c1; i < c2; i ++) {
                int tmp1 = solve(r1, c1, r2, i, m-1);
                int tmp2 = solve(r1, i+1, r2, c2, 1);
                if (tmp1 != -1 && tmp2 != -1) {
                    if (ans == -1 || ans > tmp1 + tmp2) {
                        ans = tmp1 + tmp2;
                    }
                }
            }
        }
        return f[r1][c1][r2][c2][m] = ans;
    }
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= 8; i ++) {
            for (int j = 1; j <= 8; j ++) {
                scanf("%d", &a[i][j]);
                low[i][j] = low[i][j-1] + a[i][j];
                sum[i][j] = sum[i-1][j] + low[i][j];
            }
        }
        printf("%d
    ", solve(1, 1, 8, 8, n));
        return 0;
    }
    
  • 相关阅读:
    day 08 小结
    day 07作业
    逆向---入坑记
    Codeforces Round #523 (Div. 2) B,D
    VIM一键配置
    zoj 2704 Brackets 用栈维护括号匹配 (8-A)
    zoj 2840 File Searching
    zoj 1698 Easier Done Than Said?
    13暑假集训6 总结
    13暑假集训#7 总结
  • 原文地址:https://www.cnblogs.com/quanjun/p/13191278.html
Copyright © 2011-2022 走看看