#lydlx05x0E08. 棋盘分割
棋盘分割
题目描述
将一个 的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了 次后,连同最后剩下的矩形棋盘共有 块矩形棋盘(每次切割都只能沿着棋盘格子的边进行)。

原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。
现在需要把棋盘按上述规则分割成 块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差公式:
$$\sigma = \sqrt{ \frac{ \sum_{i=1}^n (x_i - \bar{x})^2 }{n} }$$其中平均值:
为第 块矩形棋盘的总分。
请编程对给出的棋盘及 ,求出均方差的最小值。
输入格式
第 1 行为一个整数 。
第 2 行至第 9 行每行为 8 个小于 100 的非负整数,表示棋盘上相应格子的分值。每行相邻两数之间用一个空格分隔。
输出格式
输出最小均方差值(四舍五入精确到小数点后三位)。
样例
3
1 1 1 1 1 1 1 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0
1 1 1 1 1 1 0 3
1.633
样例解释
棋盘数据
,棋盘大小为 ,分值矩阵见输入。
分割要求
需要将棋盘切割成 块矩形(即切 刀),使得这 块的总分均方差最小。
计算过程
首先计算整个棋盘的总分 ,平均值 。
我们需要找到一种分割方式,使得 块棋盘的总分 满足 最小。
由于均方差 $\sigma = \sqrt{ \frac{ \sum (x_i - \bar{x})^2 }{n} }$,最小化 等价于最小化 。
最优分割
通过动态规划枚举所有可能的分割方式,可以求得最小 ,然后计算 。
根据输出,最小均方差为 。
数据范围
- (即 的取值范围是 )
- 棋盘大小固定
- 每个格子分值
算法分析
这是一个二维区间 DP问题,需要将棋盘分割成 个矩形,求最小均方差。
数学转化
设总分为 ,平均值为 。
均方差 $\sigma = \sqrt{ \frac{ \sum_{i=1}^n (x_i - \bar{x})^2 }{n} }$。
由于 是常数,最小化 等价于最小化 $\sum_{i=1}^n (x_i - \bar{x})^2 = \sum_{i=1}^n x_i^2 - 2\bar{x}\sum_{i=1}^n x_i + n\bar{x}^2 = \sum_{i=1}^n x_i^2 - \frac{sum^2}{n}$。
因为 是定值,所以最小化 等价于最小化 。
因此,问题转化为:将棋盘分割成 个矩形,使得各矩形总分平方和最小。
动态规划状态
设 表示将子矩形 到 切割成 块矩形的最小平方和。
其中 是左上角坐标, 是右下角坐标,坐标从 1 开始。
转移方程
- 如果 ,那么 。
- 如果 ,我们需要枚举切割位置和两块分别切割的块数。
- 横着切:在行 ()处切成上下两个矩形,上面切成 块,下面切成 块。$$dp = \min_{x_1 \le r < x_2, 1 \le t < k} \left( dp[x_1][y_1][r][y_2][t] + dp[r+1][y_1][x_2][y_2][k-t] \right)$$
- 竖着切:在列 ()处切成左右两个矩形,左边切成 块,右边切成 块。$$dp = \min_{y_1 \le c < y_2, 1 \le t < k} \left( dp[x_1][y_1][x_2][c][t] + dp[x_1][c+1][x_2][y_2][k-t] \right)$$
预处理
为了快速计算子矩形的总分,可以预处理二维前缀和 ,表示从 到 的矩形总分。
子矩形 到 的总分为:
$$sum = s[x_2][y_2] - s[x_1-1][y_2] - s[x_2][y_1-1] + s[x_1-1][y_1-1]$$最终答案
整个棋盘 到 切割成 块的最小平方和为 。
最小均方差为:
$$\sigma = \sqrt{ \frac{ dp[1][1][8][8][n] - \frac{sum^2}{n} }{n} }$$注意:由于 存储的是平方和,而 ,所以 $\sum (x_i - \bar{x})^2 = dp[1][1][8][8][n] - \frac{sum^2}{n}$。
复杂度分析
状态数:。 每个状态转移需要枚举切割位置和分配块数,大约 。 总计算量大约 ,可以接受。
注意事项
- 四舍五入到小数点后三位。
- 使用
double类型计算,注意精度。 - 可以记忆化搜索实现更简洁。
- 由于 , 的循环范围要注意。
实现提示
- 使用
memset初始化 DP 数组为 -1(或极大值),记忆化搜索。 - 计算前缀和便于快速得到矩形总分。
- 最后输出时使用
printf("%.3lf\n", sqrt(...))自动四舍五入。