基于3D点集的网格划分:如何用动态规划最小化总误差与网格数之和
注:原问题描述中“最终得到m*n个网格”应为笔误,实际是x轴划分为m个连续区间、y轴划分为k个连续区间后得到m×k个网格,以下解法基于这个修正后的逻辑展开。
前置预处理
首先对原始数据做预处理,方便后续快速计算任意网格的误差:
- 坐标排序去重:把所有点的x坐标去重后从小到大排序,得到有序序列
X = [x₁, x₂, ..., x_p];同理对y坐标去重排序得到Y = [y₁, y₂, ..., y_q],所有原始点都落在这个p行q列的坐标格点上。 - 前缀和数组计算:预处理三个二维前缀和数组:
cnt[i][j]:所有满足x ≤ x_i且y ≤ y_j的点的数量sum_z[i][j]:上述点的z值之和sum_z2[i][j]:上述点的z值平方之和
基于这三个数组,我们可以O(1)计算任意矩形区域x ∈ [x_a, x_b], y ∈ [y_c, y_d]的误差:
先算区域内的点数量n = cnt[b][d] - cnt[a-1][d] - cnt[b][c-1] + cnt[a-1][c-1]
区域内z和s = sum_z[b][d] - sum_z[a-1][d] - sum_z[b][c-1] + sum_z[a-1][c-1]
区域内z平方和s2 = sum_z2[b][d] - sum_z2[a-1][d] - sum_z2[b][c-1] + sum_z2[a-1][c-1]
如果n=0(区域内没有点),误差为0;否则误差为cost(a,b,c,d) = s2 - s² / n,和题目给出的误差定义完全一致。
动态规划解法
首先做一个等价转化:题目要求的总代价是「所有网格误差之和 + 网格总数」,等价于每个网格的代价是「自身误差 + 1」,求所有网格的总代价最小值,这样转化后动态规划的状态定义会更简洁。
状态定义
我们用dp[x1][x2][y1][y2]表示x区间为[x_a, x_b]、y区间为[y_c, y_d]的矩形区域,做最优网格划分的最小总代价。
边界条件
如果区域内没有点(n=0),不需要划分也没有误差,直接返回0;如果区域只有1个点,代价就是0+1=1。
状态转移
对于任意矩形区域,我们有三种可选的划分方案,取三者的最小值作为当前区域的最优解:
- 不做任何划分,整个区域作为一个网格,代价为
cost(a,b,c,d) + 1 - 沿x轴方向切分:在x区间
[a, b)之间选一个切分点k,把区域拆成[a, k] × [c, d]和[k+1, b] × [c, d]两个子区域,总代价为dp[a][k][c][d] + dp[k+1][b][c][d],遍历所有可能的k取最小值 - 沿y轴方向切分:在y区间
[c, d)之间选一个切分点l,把区域拆成[a, b] × [c, l]和[a, b] × [l+1, d]两个子区域,总代价为dp[a][b][c][l] + dp[a][b][l+1][d],遍历所有可能的l取最小值
最终结果
整个空间的最优解就是dp[1][p][1][q],也就是覆盖所有点的最大矩形区域的最小总代价。
复杂度优化说明
如果直接按上述四维DP计算,时间复杂度是O(p²q²(p+q)),适合p和q都不超过50的场景。如果坐标点数量更多,可以利用代价函数满足的四边形不等式性质,用分治优化或者Knuth优化把时间复杂度降到O(p²q + pq²),满足大部分工业场景的需求。
内容的提问来源于stack exchange,提问作者Yao Yingjie
相关产品推荐
相关产品推荐

