刚开始调半天1/4区域的,疯狂WA.
后来发现一个区域只取一个点,1/4区域并不是完全对称的,会”偏向00一点”,需要整片区域dfs.
User
1 | 四分树编码(一个简单的压缩算法) |
gpt
1 | 下面我给你一个**可直接实现的、思路完全对齐你描述的 C++ 解法**,并且把「为什么这样算」和「代码在算什么」讲清楚,方便你自己验证或改进。 |
if (窗口纯色)
return 2;
else
return 1 + sum(四个子窗口)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> 根节点没有前置 `0`,但逻辑可以统一处理
---
## 五、复杂度优化(关键)
* **不会遍历像素**
* 实际递归深度 ≤ 24
* 只有「圆边界附近」的区域会继续分裂
* 实际节点数 ≈ O(N · 2^N) 的边界规模
完全可行。
---
## 六、完整 C++ 实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using namespace std;
using int64 = long long;
static const int N = 24;
static const int64 R = (1LL << (N - 1));
static const int64 CX = R;
static const int64 CY = R;
static const int64 R2 = R * R;
/* 判断点是否在圆内 */
inline bool inside(int64 x, int64 y) {
int64 dx = x - CX;
int64 dy = y - CY;
return dx * dx + dy * dy <= R2;
}
/* 判断一个正方形窗口是否纯色
* 返回:
* 1 -> 全黑
* 0 -> 全白
* -1 -> 混合
*/
int check(int64 x, int64 y, int64 len) {
bool c1 = inside(x, y);
bool c2 = inside(x + len, y);
bool c3 = inside(x, y + len);
bool c4 = inside(x + len, y + len);
if (c1 && c2 && c3 && c4) return 1;
if (!c1 && !c2 && !c3 && !c4) return 0;
return -1;
}
/* 计算该窗口对应的最短编码长度 */
long long solve(int64 x, int64 y, int64 len) {
int state = check(x, y, len);
if (state != -1) {
// 纯色:10 或 11
return 2;
}
// 需要分割
long long res = 1; // 前导 0
int64 h = len >> 1;
// 左上、右上、左下、右下
res += solve(x, y + h, h);
res += solve(x + h, y + h, h);
res += solve(x, y, h);
res += solve(x + h, y, h);
return res;
}
int main() {
int64 size = 1LL << N;
cout << solve(0, 0, size) << "\n";
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22---
## 七、你这个思路的本质总结
你给出的核心想法非常正确:
* 四分树压缩 ≈ **统计“无法压缩的窗口”**
* 圆图像 → **只有边界产生复杂性**
* 不需要逐像素,**只判断窗口**
这是典型的 **几何 + 分治 + 树编码长度统计** 的综合题,思路已经非常接近竞赛/Project Euler 级别解法。
---
如果你愿意,我可以:
* 🔍 给你**数学上估算节点数量的渐近分析**
* 🚀 帮你改成 **完全无递归的迭代版本**
* 🧠 推导一个 **近似公式直接算 Dₙ 长度**
随时继续。
fun fact
手修了一下,调整了区间:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using namespace std;
using int64 = long long;
static const int N = 24;
static const int64 R = (1LL << (N - 1));
static const int64 CX = R;
static const int64 CY = R;
static const int64 R2 = R * R;
/* 判断点是否在圆内 */
inline bool inside(int64 x, int64 y) {
int64 dx = x - CX;
int64 dy = y - CY;
return dx * dx + dy * dy <= R2;
}
/* 判断一个正方形窗口是否纯色
* 返回:
* 1 -> 全黑
* 0 -> 全白
* -1 -> 混合
*/
int check(int64 x, int64 y, int64 len) {
bool c1 = inside(x, y);
bool c2 = inside(x + len-1, y);
bool c3 = inside(x, y + len-1);
bool c4 = inside(x + len-1, y + len-1);
if (c1 && c2 && c3 && c4) return 1;
if (!c1 && !c2 && !c3 && !c4) return 0;
return -1;
}
/* 计算该窗口对应的最短编码长度 */
long long solve(int64 x, int64 y, int64 len) {
int state = check(x, y, len);
if (state != -1) {
// 纯色:10 或 11
return 2;
}
// 需要分割
long long res = 1; // 前导 0
int64 h = len >> 1;
// 左上、右上、左下、右下
res += solve(x, y + h, h);
res += solve(x + h, y + h, h);
res += solve(x, y, h);
res += solve(x + h, y, h);
return res;
}
int main() {
// int64 size = 1LL << N;
cout << solve(0, 0, R)+solve(0,R,R)+solve(R,0,R)+solve(R,R,R)+1 << "\n";
return 0;
}