P1436 棋盘分割

https://www.luogu.com.cn/problem/P1436

题意:给出一个8*8的棋盘,让我们将其分割成n块,每一块的值为(块中所有数的和)^2

   求出在最优的分割方式下的最小值;

思路:这是一个分割问题,但直接考虑分割有点难,所以我们逆向考虑,将其想为填补问题,也就是说,将n块矩阵填补成一个8*8的矩阵的最小答案;

那么我们需要以下几步:

1.初始化,我们先求出二维前缀和,方便下文求出每一块的平方和

2.设定一个dp数组 (五维) 第一维为块数,剩下四维表示矩阵的左上端点坐标和右下端点坐标。

3.进行计算,我们将块数从小到大进行枚举,将考虑的矩阵也从小到大枚举,然后即可,

  对于一个矩阵的分割操作,我们可以有两种,假设目前矩阵为(x1,y1)到(x2,y2);

  第一种: 将矩阵进行列方面的切割,这里又可以分为两种,假设我们切在k列  

        1.将k+1以及后面的作为被切的矩阵

        2.将k+1前面的作为被切的矩阵

  第二种:同上,进行行方面的切割

代码如下:

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define LL long long
 5 #define inf 0x3f3f3f3f
 6 using namespace std;
 7 int m,a[20][20],sum[20][20];
 8 LL f[20][10][10][10][10];
 9 const int n=8;
10 inline LL calc(int x1,int y1,int x2,int y2){
11     int val=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
12     return 1LL*val*val;
13 }
14 
15 int main(){
16     scanf("%d",&m);
17     for(int i=1;i<=n;i++)
18         for(int j=1;j<=n;j++)
19             scanf("%d",&a[i][j]);
20     for(int i=1;i<=n;i++)
21         for(int j=1;j<=n;j++)
22             sum[i][j]=sum[i][j-1]+a[i][j];
23     for(int i=1;i<=n;i++)
24         for(int j=1;j<=n;j++)
25             sum[i][j]+=sum[i-1][j];
26     for(int x1=1;x1<=n;x1++)
27         for(int y1=1;y1<=n;y1++)
28             for(int x2=x1;x2<=n;x2++)
29                 for(int y2=y1;y2<=n;y2++)
30                     f[1][x1][y1][x2][y2]=calc(x1,y1,x2,y2);
31     for(int i=2;i<=m;i++)
32         for(int x1=1;x1<=n;x1++)
33             for(int y1=1;y1<=n;y1++)
34                 for(int x2=x1;x2<=n;x2++)
35                     for(int y2=y1;y2<=n;y2++){
36                         LL tmp=inf;
37                         for(int j=x1;j<x2;j++)
38                         tmp=min(tmp,f[i-1][x1][y1][j][y2]+calc(j+1,y1,x2,y2)),
39                         tmp=min(tmp,f[i-1][j+1][y1][x2][y2]+calc(x1,y1,j,y2));
40                         for(int j=y1;j<y2;j++)
41                         tmp=min(tmp,f[i-1][x1][y1][x2][j]+calc(x1,j+1,x2,y2)),
42                         tmp=min(tmp,f[i-1][x1][j+1][x2][y2]+calc(x1,y1,x2,j));
43                         f[i][x1][y1][x2][y2]=tmp;
44                     }
45     printf("%lld\n",f[m][1][1][n][n]);
46     return 0;
47 }

 

posted @ 2020-03-17 16:40  古比  阅读(145)  评论(0编辑  收藏  举报