news 2026/6/10 14:26:00

拼接覆盖问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
拼接覆盖问题

一,拼接覆盖问题

给出若干个积木块部件,要求放到指定区域内,使得没有重叠。

二,冗余面积处理

如果积木块的总面积,小于指定区域的总面积,那么可以新增若干个虚拟的最小单元,拼好之后再把这些最小单元去掉。

这样,带冗余面积的拼接覆盖问题,就转化成了常见的精确面积的覆盖问题。

三,部件和部件之间的区分问题

如果有2个重复的块,直接当他们是2个不重复的块,一般都没有问题。

四,单个部件的朝向问题

一般有3种场景:(1)只能平移(2)可以平移、旋转(3)可以平移、旋转、翻转

实际上,只要能翻转自然就能实现旋转。

拼接覆盖问题也可以转成精确覆盖问题。

二维非重复块拼接覆盖

只要枚举所有的块,每个块的每一种可能性就是dancing links的一行,待覆盖区域的每个格子就是一列。除此之外,还要限制每个块只能被用1次,这也是对应一列。

PS:如果有2个重复的块,直接当他们是2个不重复的块,也没有问题。

struct Grid { int r, c; Grid(int rr, int cc) :r(rr), c(cc) {} bool operator<(const Grid& g) const { if (r == g.r)return c < g.c; return r < g.r; } }; struct Block //一个块的所有形态 { vector<vector<Grid>>grids; Block(vector<vector<Grid>>g, int maxDr, int maxDc, const map<Grid, int>& m)//块的所有形态在最小位置包含的格子,最大偏移,待覆盖区域包含的格子 { this->m = m; for (auto& g2 : g) { for (int i = 0; i < maxDr; i++)for (int j = 0; j < maxDc; j++) { for (auto& x : g2)x.r += i, x.c += j; if (inBoard(g2))grids.push_back(g2); for (auto& x : g2)x.r -= i, x.c -= j; } } } Block() {} private: map<Grid, int>m; bool inBoard(vector<Grid>& g) { for (auto& x : g)if (!m[x])return false; return true; } }; vector<vector<Grid>> Cover(vector<Block>blocks, map<Grid, int>& mg)//所有块,待覆盖区域包含的格子编号为1,2,3... { int m = 0, maxNum = 0; for (auto& block : blocks) { m += block.grids.size(); maxNum += block.grids.size() * (block.grids[0].size()+1); } DancingLink d(m, mg.size() + blocks.size(), maxNum); int r = 0; map<int, int>mrow; for (int i = 0; i < blocks.size(); i++) { mrow[r + 1] = i + 1; for (auto& grids : blocks[i].grids) { ++r; for (auto& g : grids)d.push(r, mg[g]); d.push(r, i + 1 + mg.size()); } } d.dfs(); vector<int> rows = d.rows; vector<vector<Grid>> ans; for (auto row : rows) { int id = 0; while (!mrow[row])row--, id++;; ans.push_back(blocks[mrow[row] - 1].grids[id]); } return ans; }

应用示例:

日历拼图

三维重复块拼接覆盖

假如部分块是没有数量限制的(从0到正无穷都可以),那么只需要取消“这个块只能被用1次”这个限制对应的列即可,其他的不变。

struct Grid { int r, c, h; Grid(int rr, int cc,int hh) :r(rr), c(cc),h(hh) {} bool operator<(const Grid& g) const { if (h == g.h) { if (r == g.r)return c < g.c; return r < g.r; } return h < g.h; } }; struct Block //一个块的所有形态 { vector<vector<Grid>>grids; Block(vector<vector<Grid>>g, int maxDr, int maxDc, int maxDh, const map<Grid, int>& m)//块的所有形态在最小位置包含的格子,最大偏移,待覆盖区域包含的格子 { this->m = m; for (auto& g2 : g) { for (int i = 0; i < maxDr; i++)for (int j = 0; j < maxDc; j++)for(int k=0;k<maxDh;k++) { for (auto& x : g2)x.r += i, x.c += j, x.h += k; if (inBoard(g2))grids.push_back(g2); for (auto& x : g2)x.r -= i, x.c -= j, x.h -= k;; } } } Block() {} private: map<Grid, int>m; bool inBoard(vector<Grid>& g) { for (auto& x : g)if (!m[x])return false; return true; } }; vector<vector<Grid>> Cover(vector<Block>blocks, map<int,int>ids, map<Grid, int>& mg)//所有块,不限数量的块的id, 待覆盖区域包含的格子编号为1,2,3... { int m = 0, maxNum = 0; for (auto& block : blocks) { m += block.grids.size(); maxNum += block.grids.size() * (block.grids[0].size() + 1); } DancingLink d(m, mg.size() + blocks.size() - ids.size(), maxNum); int r = 0, c = mg.size(); map<int, int>mrow; for (int i = 0; i < blocks.size(); i++) { mrow[r + 1] = i + 1; for (auto& grids : blocks[i].grids) { ++r; for (auto& g : grids)d.push(r, mg[g]); if(ids[i]==0)d.push(r, ++c); } } d.dfs(); vector<int> rows = d.rows; vector<vector<Grid>> ans; for (auto row : rows) { int id = 0; while (!mrow[row])row--, id++;; ans.push_back(blocks[mrow[row] - 1].grids[id]); } return ans; }

应用示例:

三维T型拼图

int r,c,h,blockNum; //自定义行列数,块数 map<Grid, int> ng,mg; //ng是自定义挖掉的格子,mg是有效格子 vector<Block>blocks;//自定义每个块的所有形态在最小位置包含的格子 map<int, int>ids; vector<Grid> rotate(vector<Grid>& g) { int maxRow = 0, t; for (auto& gi : g)maxRow = max(maxRow, gi.r); for (auto& gi : g)t = gi.c, gi.c = maxRow - gi.r, gi.r = t; return g; } vector<Grid> rotate2(vector<Grid> g) { int maxH = 0, t; for (auto& gi : g)maxH = max(maxH, gi.h); for (auto& gi : g)t = gi.c, gi.c = maxH - gi.h, gi.h = t; return g; } void init1() { r = 6, c = 6, h=6, blockNum = 1; ng.clear(), mg.clear(); } void init2() { vector<Grid>v1 = { {0,0,0},{0,1,0},{0,2,0},{1,1,0} }; vector<Grid>v2 = { {0,0,0},{0,1,0},{0,2,0},{0,1,1} }, v3 = rotate2(v2), v4 = rotate2(v3), v5 = rotate2(v4); blocks[0] = Block{ { v1,rotate(v1),rotate(v1),rotate(v1),v2,rotate(v2),v3,rotate(v3),v4,rotate(v4),v5,rotate(v5)}, r, c,h, mg }; ids[0] = 1; } void solve() { init1(); int id = 0; for (int i = 0; i < r; i++)for (int j = 0; j < c; j++) for (int k = 0; k < h; k++) { if (ng[Grid{ i, j ,k }] == 0)mg[Grid{ i, j,k }] = ++id; } blocks.resize(blockNum); init2(); vector<vector<Grid>> grids = Cover(blocks,ids, mg); vector<vector<vector<int>>>v(r); for (int i = 0; i < r; i++) { v[i].resize(c); for (int j = 0; j < c; j++)v[i][j].resize(h); } for (int i = 0; i < grids.size(); i++) { for (auto& g : grids[i])v[g.r][g.c][g.h] = i + 1; } for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { for (int k = 0; k < h; k++)cout << v[i][j][k] << " "; cout << endl; } cout << endl; } } int main() { ios::sync_with_stdio(false); clock_t start, endd; start = clock(); freopen("D:ans.txt", "w", stdout); solve(); endd = clock(); double endtime = (double)(endd - start) / CLOCKS_PER_SEC; cout << "Total time:" << endtime << endl; //s为单位 return 0; }

输出:

1 1 1 2 2 2
7 7 7 10 10 10
20 20 20 23 23 23
21 21 21 31 31 31
24 21 37 36 31 32
3 3 3 4 4 4

5 1 8 9 2 11
13 7 9 9 10 27
25 20 35 9 23 27
28 35 35 35 49 27
24 37 37 36 32 32
24 3 39 36 4 33

5 5 8 8 11 11
13 13 34 42 42 42
25 25 34 34 42 27
28 28 34 49 49 49
24 30 37 36 48 32
26 39 39 41 33 33

5 14 8 43 44 11
13 29 43 43 43 54
25 29 29 50 54 54
28 29 50 50 50 54
30 30 40 48 48 48
26 26 39 41 41 33

14 14 14 44 44 44
16 16 16 51 51 51
18 16 17 52 51 53
18 18 40 52 52 47
18 30 40 52 47 47
26 19 40 41 38 47

6 6 6 12 12 12
15 6 17 45 12 53
15 15 17 45 45 53
15 22 17 45 46 53
22 22 22 46 46 46
19 19 19 38 38 38

Total time:0.953

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 21:13:54

MongoDB 未授权内存泄露漏洞(CVE-2025-14847)分析报告

一、漏洞基础信息 1.1 核心基础信息 漏洞编号&#xff1a;CVE-2025-14847漏洞别名&#xff1a;MongoBleed&#xff08;安全研究人员命名&#xff09;漏洞评级&#xff1a;高危&#xff08;High&#xff09;CVSS 评分&#xff1a;7.5&#xff08;CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S…

作者头像 李华
网站建设 2026/6/10 19:08:55

一体化雨量水位监测站

问&#xff1a;这款雷达水位监测站的核心定位是什么&#xff1f;答&#xff1a;核心定位是抗干扰型非接触式水位监测终端&#xff0c;主打“非接触、高精度、抗干扰、易操作”&#xff0c;专为破解户外复杂水文环境监测难题设计&#xff0c;核心解决传统接触式水位监测四大痛点…

作者头像 李华
网站建设 2026/6/10 15:22:58

横评后发现!碾压级的AI论文网站 —— 千笔·专业学术智能体

你是否曾为论文选题而焦虑&#xff1f;是否在深夜面对空白文档毫无头绪&#xff1f;是否反复修改却仍对表达不满意&#xff1f;MBA学生在撰写论文时&#xff0c;常常面临选题困难、框架混乱、文献检索繁琐、查重率高、格式错误等问题。这些痛点不仅消耗大量时间&#xff0c;还可…

作者头像 李华
网站建设 2026/6/10 3:19:45

DNS架构设计深度解析:分布式系统设计典范

引言&#xff1a;DNS的重要性与设计哲学 域名系统&#xff08;Domain Name System&#xff0c;DNS&#xff09;是互联网的基础设施之一&#xff0c;它将人类可读的域名&#xff08;如www.example.com&#xff09;转换为机器可读的IP地址&#xff08;如192.0.2.1&#xff09;。…

作者头像 李华
网站建设 2026/6/10 15:58:01

金仓数据库兼容MongoDB吗?医疗行业文档库迁移实践指南

金仓数据库兼容MongoDB吗&#xff1f;医疗行业文档库迁移实践指南 在日常医疗信息化建设中&#xff0c;越来越多的医院和区域卫生平台面临一个共性难题&#xff1a;电子病历、检验检查报告、影像结构化描述、健康档案等数据天然具有半结构化、动态演化、嵌套复杂的特点。传统关…

作者头像 李华
网站建设 2026/6/10 21:43:33

掌握AI写教材方法,运用专业工具生成低查重的精品教材

AI教材写作工具的探索与应用 在准备写教材之前&#xff0c;选择合适的工具真的成了“让人头疼”的事情&#xff01;如果使用普通办公软件&#xff0c;功能实在有限&#xff0c;不但框架搭建得费劲&#xff0c;格式规范也要自己手动调整&#xff1b;一旦尝试专业的AI写教材工具…

作者头像 李华