棋盘分割
对一个\(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}\),显然,它是一个定值,而方差为
于是实际上递推的为\(\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]\))
边界:\(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];
}