棋盘分割

棋盘分割

对一个\(8\times 8\)的矩形网格图进行划分,第i行第j列里的数字为\(a[i][j]\),当然,接下来的操作都是在网格线上操作的,每次操作可以将矩形网格图划分成两个矩形网格图,对任意其中一个继续同样操作,给出一个数字n,显然,进行n-1次操作后会有n个矩形网格图,定义一个矩形网格图的分数为里面所有的数字之和,求分数的方差的最小值,\(n\leq 15\)

显然,问题具有可划分性,但是不知道方差是否具有最优子结构性质,于是先对式子进行研究,设\(x_i\)为第i个矩形网格图的分数,\(\bar{x}\)为矩形网格图的平均数,不难有\(\bar{x}=\frac{\sum_{i=1}^nx_i}{n}\),显然,它是一个定值,而方差为

\[\sqrt{\frac{\sum_{i=1}^n(x_i-\bar{x})^2}{n}} \]

于是实际上递推的为\(\sum_{i=1}^n(x_i-\bar{x})^2\)的最小值,这个是具有最优子结构性质的,设\(val(y_1,x_1,y_2,x_2)\)为以\((y_1,x_1)\)为左上角,\((y_2,x_2)\)为右下角的矩形的分数,这个不难\(O(n^2)\)维护,\(O(1)\)查询,设\(dp[n][y_1][x_1][y_2][x_2]\)为以\((y_1,x_1)\)为左上角,\((y_2,x_2)\)为右下角的矩形划分n次的\(\sum_{i=1}^n(x_i-\bar{x})^2\)的最小值,于是不难有
(设\(\bar{x}\)为预先处理出的平均数,\(\&x=f[n][y_1][x_1][y_2][x_2]\))

\[x=min(x,\min_{p=y_1}^{y_2-1}\{f[n-1][y_1][x_1][p][x_2]+(val(p-1,x_1,y_2,x_2)-\bar{x})^2\}) \]

\[x=min(x,\min_{p=y_1}^{y_2-1}\{f[n-1][p-1][x_1][y_2][x_2]+(val(y_1,x_1,p,x_2)-\bar{x})^2\}) \]

\[x=min(x,\min_{p=x_1}^{x_2-1}\{f[n-1][p][x_2][y_1][x_1]+(val(y_1,p-1,y_2,x_2)-\bar{x})^2\}) \]

\[x=min(x,\min_{p=x_1}^{x_2-1}\{f[n-1][y_1][p-1][y_2][x_2]+(val(p,x_2,y_1,x_1)-\bar{x})^2\}) \]

边界:\(f[0][i][j][k][l]=val(i,j,k,l)\)

答案:\(\sqrt{\frac{f[n-1][1][1][8][8]}{n}}\)

参考代码:

不具有明显阶段性,故用dfs实现

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define il inline
#define ri register
using namespace std;
int a[9][9];
bool is[16][9][9][9][9];
double dp[16][9][9][9][9],x_,
    dfs(int,int,int,int,int);
il int val(int,int,int,int);
il double min(double,double),pow2(double);
int main(){
    int n;scanf("%d",&n);
    for(int i(1),j;i<9;++i)
        for(j=1;j<9;++j)
            scanf("%d",&a[i][j]),x_+=a[i][j],
                a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];
    x_/=n,memset(dp,66,sizeof(dp));
    for(int i(1),j,k,l;i<9;++i)
        for(j=1;j<9;++j)
            for(k=i;k<9;++k)
                for(l=j;l<9;++l)
                    dp[0][i][j][k][l]=pow2(val(i,j,k,l)-x_),
                        is[0][i][j][k][l]|=true;
    printf("%.3f",sqrt(dfs(n-1,1,1,8,8)/n));
    return 0;
}
il double pow2(double x){
    return x*x;
}
il double min(double a,double b){
    return a<b?a:b;
}
double dfs(int n,int y1,int x1,int y2,int x2){
    double &x(dp[n][y1][x1][y2][x2]);
    if(is[n][y1][x1][y2][x2])return x;
    int lsy(1);
    for(int p(y1);p<y2;++p)
        x=min(x,dfs(n-1,y1,x1,p,x2)+pow2(val(p+1,x1,y2,x2)-x_)),
            x=min(x,dfs(n-1,p+1,x1,y2,x2)+pow2(val(y1,x1,p,x2)-x_));
    for(int p(x1);p<x2;++p)
        x=min(x,dfs(n-1,y1,x1,y2,p)+pow2(val(y1,p+1,y2,x2)-x_)),
            x=min(x,dfs(n-1,y1,p+1,y2,x2)+pow2(val(y1,x1,y2,p)-x_));
    return is[n][y1][x1][y2][x2]|=true,x;
}
il int val(int y1,int x1,int y2,int x2){
    return a[y2][x2]+a[y1-1][x1-1]-a[y2][x1-1]-a[y1-1][x2];
}
posted @ 2019-06-11 08:03  a1b3c7d9  阅读(104)  评论(0编辑  收藏  举报