news 2026/6/15 18:36:01

拼接覆盖问题

作者头像

张小明

前端开发工程师

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/15 12:24:33

Dollar Shave Club

1. 起源与颠覆性模式创立时间&#xff1a; 2011年&#xff0c;由 迈克尔杜宾 和 马克莱文 创立。核心模式&#xff1a; 采用 “剃须刀即服务” 的订阅制。用户每月支付固定费用&#xff08;如1美元起&#xff09;&#xff0c;即可收到高品质刀片和剃须配件直接寄到家门口。成名…

作者头像 李华
网站建设 2026/6/15 12:27:35

当“学术规范”成了AI嫌疑的通行证:我们正在用算法审判认真

在2026年的高校论文审核体系中&#xff0c;一个悖论正在愈演愈烈&#xff1a; 你越遵守学术规范&#xff0c;越像用了AI&#xff1b;你越用心写作&#xff0c;越被系统怀疑。 这不是技术的胜利&#xff0c;而是一场静默的误判—— 无数学生在深夜台灯下逐字打磨的成果&#xf…

作者头像 李华
网站建设 2026/6/15 14:42:13

当“写得像论文”需要技术辩护:我们正在用算法惩罚最诚实的人

在一个人工智能可以生成万字论文的时代&#xff0c;最讽刺的现实不是机器冒充人类&#xff0c; 而是人类因写得太像“人写的论文”&#xff0c;被当作机器。 2026年&#xff0c;无数高校学子正陷入一场无声的困境&#xff1a; 你没用AI&#xff0c;却因逻辑清晰被标记&#xf…

作者头像 李华
网站建设 2026/6/15 12:20:25

HoRain云--Python动态变量名:正确用法与最佳实践

&#x1f3ac; HoRain 云小助手&#xff1a;个人主页 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站&#xff0c;性价比超高&#xff0c;大内存超划算&#xff01;忍不住分享一下给大家。点击跳转到网站。 目录 ⛳️ 推荐 …

作者头像 李华
网站建设 2026/6/15 15:33:20

C/C++新年烟花代码

系列文章 序号直达链接1C/C李峋同款跳动的爱心2C/C跳动的爱心3C/C经典爱心4C/C满屏飘字5C/C大雪纷飞6C/C炫酷烟花7C/C黑客帝国同款字母雨8C/C樱花树9C/C奥特曼10C/C精美圣诞树11C/C俄罗斯方块小游戏12C/C贪吃蛇小游戏13C/C孤单又灿烂的神14C/C闪烁的爱心15C/C哆啦A梦16C/C简单…

作者头像 李华
网站建设 2026/6/12 4:23:49

新手也能上手 AI论文平台,千笔 VS 锐智 AI,MBA专属写作利器!

随着人工智能技术的迅猛发展&#xff0c;AI辅助写作工具已逐渐成为高校学生撰写毕业论文的重要帮手。无论是开题报告、文献综述还是正文撰写&#xff0c;越来越多的学生开始借助AI工具提升效率、降低写作压力。然而&#xff0c;面对市场上种类繁多的AI写作平台&#xff0c;许多…

作者头像 李华