棋盘分割

棋盘分割

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

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

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

于是实际上递推的为(sum_{i=1}^n(x_i-ar{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-ar{x})^2)的最小值,于是不难有
(设(ar{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)-ar{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)-ar{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)-ar{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)-ar{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];
}
原文地址:https://www.cnblogs.com/a1b3c7d9/p/11001561.html