• 洛谷 P1436 棋盘分割 题解


    题目链接

     

     

     

    题解

     

    一道区间dp好题

    用f[x1][y1][x2][y2][k]状态表示:

    1) 集合:划分到k−1个的子矩阵,是以(x1,y1)为左上角,(x2,y2)为右下角

    2) 属性:平方和的最大值

     

    我们按照每次分割作为状态划分依据;

    模拟上述集合的划分枚举所有的区间即可

    由于维数较大,五重循环过于麻烦,所以这道题我们采用记忆化搜索;

     

    代码

     

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int N = 15,M = 9;
    const int INF = 1e9;
    int  f[M][M][M][M][N];
    
    int s[N][N],n,m = 8;
    
    int get(int x1,int y1,int x2,int y2)
    {
        int sum = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
        return  sum * sum;
        
    }
    
    int  dp(int x1, int y1, int x2, int y2, int k)
    {
        int &v = f[x1][y1][x2][y2][k];
        if (v >= 0) return v;
        if (k == 1) return v = get(x1, y1, x2, y2);
    
        v = INF;
        for (int i = x1; i < x2; i ++ )
        {
            v = min(v, get(x1, y1, i, y2) + dp(i + 1, y1, x2, y2, k - 1));
            v = min(v, get(i + 1, y1, x2, y2) + dp(x1, y1, i, y2, k - 1));
        }
    
        for (int i = y1; i < y2; i ++ )
        {
            v = min(v, get(x1, y1, x2, i) + dp(x1, i + 1, x2, y2, k - 1));
            v = min(v, get(x1, i + 1, x2, y2) + dp(x1, y1, x2, i, k - 1));
        }
    
        return v;
    }
    
    int main()
    {
        cin >> n;
        for (int i = 1; i <= m; i ++ )
            for (int j = 1; j <= m; j ++ )
            {
                cin >> s[i][j];
                s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
            }
        memset(f, -1, sizeof f);
        printf("%d", (dp(1, 1, 8, 8, n)));
    
        return 0;
    }
  • 相关阅读:
    20145220&20145209&20145309信息安全系统设计基础实验报告
    20145209 《信息安全系统设计基础》第8周学习总结
    R574
    gym102219
    102222F
    luogu 1337
    luogu 2503 & bzoj 2428
    18 BJ J
    poj 1981
    101992 I
  • 原文地址:https://www.cnblogs.com/yjyl0098/p/14636599.html
Copyright © 2020-2023  润新知