给定由xy平面中的位置列表描述的路径P,每个位置由边连接,计算必须从P移除的边的最小数量,使得P不会关闭xy中的任何区域平面(即,应该可以从任何点到任何其他点)。每个位置都有整数坐标,每个位置将是前一个位置左,右,上或下的一个单位。
例如,如果P = {[0,0], [0,1], [1,1], [1,0], [0,0]}
,那么路径是一个正方形,从(0,0)开始。方形的4个边缘中的任何一个都可以被移除,因此答案是1。
请注意,可以绘制两次相同的边。也就是说,如果P = {[0,0], [0,1], [1,1], [1,0], [0,0], [0,1], [1,1], [1,0], [0,0]}
,则答案为2,因为现在正方形的每一边都有2条边,因此必须至少删除2条边以“释放”正方形。
我尝试过一种天真的方法,如果任何位置被访问两次,可能会有一个封闭的区域(并非总是如此,但我的程序依赖于这个假设),所以我将1添加到删除的最小边数。通常,如果访问顶点N次,我将N-1添加到删除的边数。但是,例如,如果P = {[0,0], [0,1], [0,0]}
,则没有封闭区域,而我的程序会认为存在。它崩溃的另一种情况:如果P = {[0,0], [0,1], [1,1], [1,0], [0,0], [1,0]}
,我的程序将输出2(因为(0,0)和(0,1)每次访问两次),而正确的答案是1,因为我们可以移除广场的其他三面。
似乎有两个主要的子任务来解决这个问题:首先,给定路径,找出哪些位置是封闭的(即,弄清楚路径将图分割成的区域);第二,利用这些区域的知识来确定必须去除哪些边缘以防止封闭。
任何提示,伪代码或代码都将受到赞赏。
来源:普林斯顿大学高级本科生课程。
答案 0 :(得分:0)
以下是一些可能有用的想法。我假设你有n
分。
您可以先在集S
中插入所有边,以便删除重复的边:
for(int i = 0; i < n-1; i++)
S.insert( {min(p[i], p[i+1), max(p[i], p[i+1])} );
现在再次迭代边缘并构建图形。然后在此图中找到最长的简单路径。
结果图是二分的(如果存在一个循环,它必须具有偶数长度)。这条信息也可能有所帮助。
答案 1 :(得分:0)
您可以使用泛光填充算法查找路径创建的平面的连续区域。其中一个区域是无限的,但很容易通过扫描线扫描来计算周长,这将限制总大小不会比路径长度的二次方差更差。如果路径长度小于1,000,则可以接受二次方。 (编辑:我后来意识到,由于只需要识别与线边缘相邻的区域,您可以通过对线段进行排序然后应用扫描线扫描来进行此计算,从而产生O( n log n)时间复杂度。)
路径中的每条边都在两个区域之间(或者是无关紧要的,因为两边的方块都是相同的区域)。对于相关边,您可以计算重复次数,然后找到任意一对相邻区域之间的最小成本边界。一旦确定了每个方格的区域ID,所有这些都是线性的。
现在你有一个加权图。构造最小生成树。这应该是需要移除的最小边缘集合。
可能有一个更聪明的解决方案。洪水填充让我感到蛮力和天真,但这是我在十分钟内能做到的最好的事情。
祝你好运。