考虑一个潜在的自相交多边形,由2D空间中的一系列顶点定义。例如
{{0, 0}, {5, 0}, {5, 4}, {1, 4}, {1, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 1}, {4, 1}, {4, 5}, {0, 5}}
有几种方法可以定义这种多边形的面积,但是最有趣的一种是奇偶规则。选取平面中的任何点,从该点到无穷远(沿任何方向)画一条线。如果该线与多边形交叉的次数是奇数次,则该点是该多边形区域的一部分;如果该线与多边形交叉的次数是偶数,则该点不属于多边形的一部分。对于上面的示例多边形,这是它的轮廓以及奇数面积:
多边形通常不会正交。我只选择了这样一个简单的示例,以便更轻松地计算面积。
此示例的区域为17
(不是,24
或者33
不像其他定义或区域那样)。
请注意,在此定义下,多边形的面积与其缠绕顺序无关。
挑战
给定具有定义多边形的整数坐标的顶点列表,请确定其在奇偶规则下的面积。
您可以编写函数或程序,通过STDIN或最接近的替代方法,命令行参数或函数参数获取输入,然后返回结果或将结果打印到STDOUT或最接近的替代方法。
您可以采用任何方便的列表或字符串格式的输入,只要不进行预处理即可。
结果应该是浮点数,精确到6个有效数字(十进制),或者是一个有理结果,其浮点表示形式精确到6个有效数字。(如果您得出合理的结果,它们可能会是准确的,但是我不能要求这样做,因为我没有确切的结果可供参考。)
您必须能够在合理的台式机上在10秒内解决以下每个测试用例。(此规则有一定的余地,因此请使用您的最佳判断。如果在我的笔记本电脑上花费20秒,我会带给您疑问的好处,如果花费一分钟,我不会。)我认为这个限制应该非常大方,但是应该排除那些仅在足够细的网格上离散多边形并计数的方法,或者使用诸如蒙特卡洛这样的概率方法。做一个好运动员,不要试图优化这些方法,以使您无论如何都可以满足时间限制。;)
您不得使用任何与多边形直接相关的现有功能。
这是代码高尔夫球,因此最短的提交(以字节为单位)获胜。
假设条件
- 所有的坐标都在范围内的整数
0 ≤ x ≤ 100
,0 ≤ y ≤ 100
。 - 会有至少
3
在最50
顶点。 - 不会有任何重复的顶点。顶点也不会位于另一边上。(不过,列表中可能有共线的点。)
测试用例
{{0, 0}, {5, 0}, {5, 4}, {1, 4}, {1, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 1}, {4, 1}, {4, 5}, {0, 5}}
17.0000
{{22, 87}, {6, 3}, {98, 77}, {20, 56}, {96, 52}, {79, 34}, {46, 78}, {52, 73}, {81, 85}, {90, 43}}
2788.39
{{90, 43}, {81, 85}, {52, 73}, {46, 78}, {79, 34}, {96, 52}, {20, 56}, {98, 77}, {6, 3}, {22, 87}}
2788.39
{{70, 33}, {53, 89}, {76, 35}, {14, 56}, {14, 47}, {59, 49}, {12, 32}, {22, 66}, {85, 2}, {2, 81},
{61, 39}, {1, 49}, {91, 62}, {67, 7}, {19, 55}, {47, 44}, {8, 24}, {46, 18}, {63, 64}, {23, 30}}
2037.98
{{42, 65}, {14, 59}, {97, 10}, {13, 1}, {2, 8}, {88, 80}, {24, 36}, {95, 94}, {18, 9}, {66, 64},
{91, 5}, {99, 25}, {6, 66}, {48, 55}, {83, 54}, {15, 65}, {10, 60}, {35, 86}, {44, 19}, {48, 43},
{47, 86}, {29, 5}, {15, 45}, {75, 41}, {9, 9}, {23, 100}, {22, 82}, {34, 21}, {7, 34}, {54, 83}}
3382.46
{{68, 35}, {43, 63}, {66, 98}, {60, 56}, {57, 44}, {90, 52}, {36, 26}, {23, 55}, {66, 1}, {25, 6},
{84, 65}, {38, 16}, {47, 31}, {44, 90}, {2, 30}, {87, 40}, {19, 51}, {75, 5}, {31, 94}, {85, 56},
{95, 81}, {79, 80}, {82, 45}, {95, 10}, {27, 15}, {18, 70}, {24, 6}, {12, 73}, {10, 31}, {4, 29},
{79, 93}, {45, 85}, {12, 10}, {89, 70}, {46, 5}, {56, 67}, {58, 59}, {92, 19}, {83, 49}, {22,77}}
3337.62
{{15, 22}, {71, 65}, {12, 35}, {30, 92}, {12, 92}, {97, 31}, {4, 32}, {39, 43}, {11, 40},
{20, 15}, {71, 100}, {84, 76}, {51, 98}, {35, 94}, {46, 54}, {89, 49}, {28, 35}, {65, 42},
{31, 41}, {48, 34}, {57, 46}, {14, 20}, {45, 28}, {82, 65}, {88, 78}, {55, 30}, {30, 27},
{26, 47}, {51, 93}, {9, 95}, {56, 82}, {86, 56}, {46, 28}, {62, 70}, {98, 10}, {3, 39},
{11, 34}, {17, 64}, {36, 42}, {52, 100}, {38, 11}, {83, 14}, {5, 17}, {72, 70}, {3, 97},
{8, 94}, {64, 60}, {47, 25}, {99, 26}, {99, 69}}
3514.46
upath
和lineto
听起来好像您实际上是在预处理输入。也就是说,您不是要获取坐标列表,而是要获取实际的多边形。
CrossingPolygon
。
upath
运算符来解析整个内容。(实际上,分隔符之间是一个非常简单的1:1转换。}, {
只是变为lineto
,并且删除了x和y之间的逗号,并且将开括号和闭括号替换为静态的页眉和页脚...)