LuoguP1436 棋盘分割 题解

Posted acceptedzhs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LuoguP1436 棋盘分割 题解相关的知识,希望对你有一定的参考价值。

嗯,点开题目,哇!是一道闪亮亮的蓝题!

不要被吓到了,其实,这道题就是一个简单的DP啦!

我们设 (f[x1][y1][x2][y2][c]) 为以 ((x1,y1)) 为左上角,以 ((x2,y2)) 为右上角的矩形分割成c个部分所取得的最大分数。

枚举每一行(列),将其分割成两部分,然后考虑是继续分割上(左)边还是下(右)边

所以,转移方程就出来啦!

(f[x1][y1][x2][y2][c]=min(min(f[x1][y1][x][y2][c-1]+sum[x+1][y1][x2][y2]^2,f[x+1][y1][x2][y2][c-1]+sum[x1][y1][x][y2]^2) ,)

(min(f[x1][y1][x2][y][c-1]+sum[x1][y+1][x2][y2]^2,f[x1][y+1][x2][y2][c-1]+sum[x1][y1][x2][y]^2)))

((x1 leq x < x2,y1 leq y < y2))

边界情况:当 (c=1,f[x1][y1][x2][y2][c]=sum[x1][y1][x2][y2])

最后结果即为 (f[1][1][8][8][c])

(sum[x1][y1][x2][y2][c]) 为以 ((x1,y1)) 为左上角,以 ((x2,y2)) 为右上角的矩形内的总分数

(sum) 进行预处理,这里要算出二维前缀和,设为 (s[i][j])

(sum[x1][y1][x2][y2]=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])

好了,就这样,一个完美的DP就出来啦!

也就六重循环吗)

欢乐的贴代码时间:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,a[9][9],f[9][9][9][9][16];
int s[9][9],sum[9][9][9][9];
int main(){
    memset(f,0x3f,sizeof(f));
    scanf("%d",&n);
    for(int i=1;i<=8;i++){
        for(int j=1;j<=8;j++){
            scanf("%d",&a[i][j]);
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
        }
    }
    for(int i=1;i<=8;i++){
        for(int j=1;j<=8;j++){
            for(int k=i;k<=8;k++){
                for(int l=j;l<=8;l++){
                    sum[i][j][k][l]=s[k][l]-s[i-1][l]-s[k][j-1]+s[i-1][j-1];
                    f[i][j][k][l][1]=sum[i][j][k][l]*sum[i][j][k][l];
                }
            }
        }
    }
    for(int c=2;c<=n;c++){
        for(int len1=1;len1<=8;len1++){
            for(int i=1,j=len1;j<=8;i++,j++){
                for(int len2=1;len2<=8;len2++){
                    for(int k=1,l=len2;l<=8;k++,l++){
                        int x1=i,y1=k,x2=j,y2=l;
                        for(int row=x1;row<x2;row++){
                            f[x1][y1][x2][y2][c]=min(min(f[x1][y1][x2][y2][c],                            f[x1][y1][row][y2][c-1]+sum[row+1][y1][x2][y2]*sum[row+1][y1][x2][y2]),                            f[row+1][y1][x2][y2][c-1]+sum[x1][y1][row][y2]*sum[x1][y1][row][y2]);
                        }
                        for(int col=y1;col<y2;col++){
                            f[x1][y1][x2][y2][c]=min(min(f[x1][y1][x2][y2][c],                            f[x1][y1][x2][col][c-1]+sum[x1][col+1][x2][y2]*sum[x1][col+1][x2][y2]),                            f[x1][col+1][x2][y2][c-1]+sum[x1][y1][x2][col]*sum[x1][y1][x2][col]);
                        }
                    }
                }
            }
        }
    }
    printf("%d
",f[1][1][8][8][n]);
    return 0;
}

本人蒟蒻,求大佬指教~~~~

以上是关于LuoguP1436 棋盘分割 题解的主要内容,如果未能解决你的问题,请参考以下文章

DP专题——棋盘分割

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

luogu P1549 棋盘问题 题解

棋盘制作

LuoguP3930 SAC E#1 - 一道大水题 Knight

[luoguP1169] [ZJOI2007]棋盘制作(单调栈)