zoukankan      html  css  js  c++  java
  • 【Luogu】P1436 棋盘分割 题解

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

    不要被吓到了,其实,这道题就是一个简单的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\n",f[1][1][8][8][n]);
        return 0;
    }
    

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

  • 相关阅读:
    快速幂
    某年元宵节大礼包 矩阵快速幂
    HDU 3303 Harmony Forever 前缀和+树状数组||线段树
    HDU 4325 Flowers 树状数组+离散化
    11、【设计模式】构建器模式
    【基础】数据类型
    【Mybatis】Mybatis缓存
    【FTP】FTP(文件传输协议)工作原理(SFTP)
    Docker是什么
    【RabbitMQ】使用RabbitMQ实现延迟任务
  • 原文地址:https://www.cnblogs.com/acceptedzhs/p/12173658.html
Copyright © 2011-2022 走看看