Algorithm 人工检查器与程序员(was:检测是否有圆圈重叠的算法)
问题 这个问题实际上是在今天的工作中提出来的。我们正在计划一项实验,向用户展示一系列地图。每张地图上有31个符号。每个符号也有一个标签。我们注意到,在少数情况下,标签重叠,导致其中一个标签无法读取 我们最终以老式的方式识别问题符号——通过逐个查看地图并记下我们发现的任何问题符号的ID——但我认为这个问题可以用算法很容易地解决。目视检查所有地图(使用公认笨重的实验数据收集工具)大约需要一个人小时 我很好奇这个网站上的人能以多快的速度解决这个问题,我也对你提出的算法感兴趣。(注意:这不是一个家庭作业问题,尽管我认为这会成为一个有趣的家庭作业或面试问题。) 规格Algorithm 人工检查器与程序员(was:检测是否有圆圈重叠的算法),algorithm,language-agnostic,Algorithm,Language Agnostic,问题 这个问题实际上是在今天的工作中提出来的。我们正在计划一项实验,向用户展示一系列地图。每张地图上有31个符号。每个符号也有一个标签。我们注意到,在少数情况下,标签重叠,导致其中一个标签无法读取 我们最终以老式的方式识别问题符号——通过逐个查看地图并记下我们发现的任何问题符号的ID——但我认为这个问题可以用算法很容易地解决。目视检查所有地图(使用公认笨重的实验数据收集工具)大约需要一个人小时 我很好奇这个网站上的人能以多快的速度解决这个问题,我也对你提出的算法感兴趣。(注意:这不是一个家庭作业
- 地图:24
- 地图大小(像素):1024 X 768
- 每个地图的符号(圆圈):31
- 符号直径(像素):60
(范围:1-24)MapId
(范围:1-744(24个地图x 31个符号/地图=744个总符号)SymbolId
(范围:0-1024)XCoordinate
(范围:0-768)YCoordinate
整数
目标
你能以多快的速度想出一个算法(你选择的语言):
SymbolId
s的报告不符合要求If distance(A.center, B.center) < (A.radius+B.radius)
the circles overlap.
如果距离(A.中心,B.中心)<(A.半径+B.半径)
圆圈重叠。
在你的例子中,似乎每个圆都有相同的半径,但我考虑了每个圆有不同半径的可能性,以防万一
至于要想多久,有点难说——比加载完整描述的页面所花的时间要少。然后我必须阅读一些资料,以确认基本问题是从标题看出来的是什么
编辑:如果你有很多圆圈,可能值得做一些排序来消除不必要的重叠测试,但如果每张地图只有30个圆圈,那可能不值得——你需要一台真正古老的计算机来完成这项工作,需要一整秒钟
对不起,我必须离开一段时间让孩子们参加一个滚轴曲棍球比赛。不管怎样,虽然我还没有测试过,但我在C++中的程序大概是10-12分钟,我必须在那里打个电话,所以我没有确切的时间):
#包括
#包括
#包括
结构点{
int-id,x,y;
};
std::istream&operator>>(std::istream&is,point&p){
返回值为>>p.id>>p.x>>p.y;
}
typedef-std::向量映射;
双区(点常数和a,点常数和b){
双x=a.x-b.x;
双y=a.y-b.y;
返回sqrt(x*x+y*y);
}
int main(){
std::矢量地图(24);
int mapID;
而(std::cin>>mapID){
点温;
标准:cin>>温度;
映射[mapID]。推回(临时);
}
对于(int i=0;i我的第一个想法是Jerry已经发布的简单的O(N2)算法,除了一个小的例外:距离2更容易计算,因为它不需要平方根,所以将其与(半径之和)2进行比较
我的第二个想法是通过包含您的所有观点的解决方案来增强该解决方案,这有助于减少需要进行的比较的数量
写这个答案要比想出这两种解决方案花费更长的时间——也许10秒。这种问题在计算机图形学中很常见,我只是在重复我以前看到的
在Haskell中快速编写解决方案1的实现(耗时不到一分钟):
import-Control.Monad
导入数据。列表
半径=30
main=do
点如果你在寻找加速答案的方法,你也可以尝试“扫除和修剪”。这里有一些比O(n^2)更快的方法其中n=符号数。使用动态数组矩阵,如STLvector
来表示图像中的每个像素。计算每个圆所占用的像素,并将其symbol
推入圆中每个像素的数组中。处理完所有圆后,只需查看每个像素,如果有任何像素具有如果数组中有多个符号,您就知道哪个symbold
s是冲突的
所用时间:~5分钟
更新:根据新的要求,我的初始算法可以稍加修改,以读取每一行,更新上面为每个符号定义的像素-符号地图,然后转到下一个地图。假设您的电子表格软件具有SQL功能,我会通过查询运行它:
select
s1.symbolId,s2.symbolId
from
symbols s1
join
symbols s2
where
s1.mapid=s2.mapid
and
s1.symbolid<s2.symbolid
and
((s1.xcoordinate-s2.xcoordinate)*
(s1.xcoordinate-s2.xcoordinate)+
(s1.ycoordinate-s2.ycoordinate)*
(s1.ycoordinate-s2.ycoordinate))
<(r+r)*(r+r)
选择
s1.符号化,s2.符号化
从…起
符号s1
参加
符号s2
哪里
s1.mapid=s2.mapid
及
s1.符号数据XCoordinate
和YCoordinate
整数?是的,我编辑了m
import Control.Monad
import Data.List
radius = 30
main = do
points <- fmap (map (map read . words) . lines) getContents
mapM_ print $ overlapping (points :: [[Int]])
overlapping list = do
[m1, s1, x1, y1]:rest <- tails list
[m2, s2, x2, y2] <- rest
guard $ m1 == m2 && (x2-x1)^2 + (y2-y1)^2 < 2*radius^2
return ((m1, s1), (m2, s2))
select
s1.symbolId,s2.symbolId
from
symbols s1
join
symbols s2
where
s1.mapid=s2.mapid
and
s1.symbolid<s2.symbolid
and
((s1.xcoordinate-s2.xcoordinate)*
(s1.xcoordinate-s2.xcoordinate)+
(s1.ycoordinate-s2.ycoordinate)*
(s1.ycoordinate-s2.ycoordinate))
<(r+r)*(r+r)