算法:圆盘盖米问题(圆的密铺?)

2019-05-08 13:10:23 +08:00
 caneman

原问题为:

在一棋盘撒米,米粒落点不一,有口径大小不一的若干圆盘,问如何尽可能少的尝试,用圆盘覆盖尽可能多的米粒?(即:尽可能少的米粒裸露在外。)

条件:

1.黑盒系统,米粒位置信息均不可知。

2.仅当圆盘放下方可知其覆盖米粒数量,,每个圆盘覆盖的米粒不得超过 50 粒。

3.圆盘之间可以互相堆叠,已被下层圆盘覆盖的米粒不计入上层圆盘覆盖米粒的数量。

下面是我想到的一种解决方案,感觉还有很多地方可以优化,请问大伙有没有什么好的办法或者对这个算法的改进?

2948 次点击
所在节点    Python
25 条回复
caneman
2019-05-08 13:17:32 +08:00
大伙给点思路啊
fzy0728
2019-05-08 13:36:45 +08:00
图裂了
widewing
2019-05-08 13:45:26 +08:00
那不是只要重叠面积尽量小不就好了
caneman
2019-05-08 13:46:33 +08:00
@fzy0728

我这里看没有啊

链接:



![avatar]( )
ipwx
2019-05-08 13:47:16 +08:00
@caneman imgur 是被墙的域名。。。
CEBBCAT
2019-05-08 13:49:09 +08:00
楼主你没说一共多少粒米。这怎么解?要是他把所有米都放到一个点上那一准爆掉
@fzy0728 科学上网
weizhen199
2019-05-08 13:49:11 +08:00
= -端起来抖一抖
caneman
2019-05-08 13:49:59 +08:00
caneman
2019-05-08 13:51:06 +08:00
@CEBBCAT 随机掉落,单个点重叠数量<50
caneman
2019-05-08 13:52:07 +08:00
@CEBBCAT 用足够大的圆盘盖一下就知道了,所以可以理解为知道总数。
fzy0728
2019-05-08 16:34:41 +08:00
CEBBCAT
2019-05-08 16:45:34 +08:00
@fzy0728 #11 哦嚯,这 Imgur 也是有意思 http://discuss.flarum.org.cn/d/359 我该嫖哪个图床啊,哭
necomancer
2019-05-08 20:25:54 +08:00
我觉得就是怎么用圆有效填充方形面积的问题。
1.圆盘大小限定死了吗?如果圆盘大小是限定的,则用六方堆积圆盘,你用了立方堆积,很浪费空间。
2.如果有大有小,则尽可能用最大圆盘进行六方堆积,用尽以后空白处用次一号的圆进行六方堆积。
米粒随机意味着我可以认为米粒是均匀分布,米粒密度 x 圆盘大小为圆盘下覆盖米粒数的期望;圆下米粒数服从二项分布,假设 p=圆盘面积(A)/底面积,则 P(n; N, A) NCn p^n(1-p)^(N-n) 为总 N 粒米,圆盘下 n 粒米的概率,所以期望是 Np, 方差是 Np(1-p),你可以用来估计某面积圆盘下大过 50 粒米的概率,最后对大圆盘进行加强覆盖。

所以,我觉得一个很简单的方案是选一个 p(50; N, A) 比较小的某个大小的圆盘进行六方堆叠,判定一下如果有超过 50 个粒子的在上面直接覆盖一个圆盘完事。因为当圆直径 /平面边长比较小(<0.3)的时候,数密度大概是 0.25 ,也就是方形面积 x0.25 个圆,能够达到 0.91 的覆盖率。平均每个圆大概覆盖 22% 左右的米粒。

参考:
https://en.wikipedia.org/wiki/Circle_packing
https://en.wikipedia.org/wiki/Circle_packing_in_a_square
necomancer
2019-05-08 20:36:51 +08:00
抱歉,最后写得有点脑残:
方形面积 x 0.25 个圆,覆盖 0.91 的面积,平均每个圆覆盖 3.64% 的面积,或者在均匀分布下,3.64%的米粒……
necomancer
2019-05-08 20:43:05 +08:00
如果涉及大圆超过 50 个粒子,需要在大圆上覆盖其他圆的时候,参考:
https://en.wikipedia.org/wiki/Circle_packing_in_a_circle
圆里继续做堆积……

我感觉你问的问题还是有点 bug 的……其实如果每个圆选取时个数时无限的,大小随意,需求是覆盖所有米粒,那么是不是一直拿能盖住所有粒子的圆往上堆,到 米粒总数 /50 个圆完事……
caneman
2019-05-09 09:47:17 +08:00
@necomancer

米粒落点并不是均匀的,有的地方稀疏有的地方稠密,有的地放可能很大一块面积没有任何米粒,有的地方可能挤的满满的,甚至一个米粒上面堆叠了另一个米粒(但是单点堆积数<50 ),不知道棋盘上米粒的密度分布情况(黑盒),只有当圆盘落下才会知道圆盘盖到了多少米粒,仅有此一项数据输出。

圆盘可以任意大小,圆盘可以撤掉 /更换(撤掉不计入次数),我上面那个圆上堆小圆的思路是把大圆撤掉用小圆去覆盖原来大圆的位置。

另外,尽可能少的尝试次数(这个次数不是到最后的使用盘子数,而是整个过程中用过盘子的总次数(撤掉盘子不计入总次数),例如放了个大盘,其覆盖米粒大于 50,撤掉大盘,改成 5 个小盘,每个小盘覆盖<50,满足条件,总的尝试次数为 1+5=6 次)。

可以不覆盖全部粒子,尽可能少的圆盘总使用次数去覆盖尽可能多的米粒,寻找一个平衡吧。

这个问题应该是没有 BUG 的,有的话欢迎再一起讨论,天体物理学中粒子密度分布计算,好像有涉及到类似的问题。

PS:圆里面做堆积的资料很有用,谢谢!
caneman
2019-05-09 09:48:35 +08:00
@fzy0728
这个可以打开吗?
http 冒号 //www 点 caneman.cn/wp-content/uploads/2019/05/dock.jpg
caneman
2019-05-09 10:15:52 +08:00

图裂的试试这个:
http://www.caneman.cn/wp-content/uploads/2019/05/2019-05-09-10-13-09.png
( http 冒号 //www 点 caneman 点 cn/wp-content/uploads/2019/05/2019-05-09-10-13-09 点 png )
fzy0728
2019-05-09 16:06:43 +08:00
尽可能少的尝试...如果是我的话会先预测米粒的分布,最少的尝试找到米粒的分布情况用圆进行分割。说一下我的想法哈,如果可以的话用(尽可能少,心里可以承受的一个值) k 个圆随机分布棋盘,类似于蒙特卡洛方法去预测棋盘上米粒分布,例如整个棋盘面积和覆盖圆面积下的米粒个数,计算大致棋盘米粒数,再根据圆盘下的米粒个数大致划分棋盘,为子棋盘,再对子棋盘用圆去划分。"近似估计+分割+覆盖"
necomancer
2019-05-10 01:57:54 +08:00
嗯……既然米粒空间分布不可知,那么第一次,比如我选择大过底面的圆覆盖,算不算我已经知道了米粒的空间分布信息?还是只返回一个米粒个数?如果只返回米粒个数,假设粒子数也比较多,那么可不可以这样尝试:
1. 使用一个大圆求出总粒子数;>50 撤掉,<50 问题解决;
2. 四等分底面,用四个圆分别覆盖,<50 保留并跳过此 1/4 的区间,>50 撤掉并将这个区间继续四等分
重复以上步骤,直到所有圆下面粒子<50,是不是 O(Log(A)) 次尝试?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/562157

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX