我在2011年加拿大计算机竞赛中遇到了一个问题(高级部门问题5),我不知道如何解决它。这是一个问题:
你走过一排K(4≤K≤25)灯,其中一些灯亮,其中一些灯关闭。在此初始配置中,没有连续的四个灯亮序列。每当连续四个或更多灯点亮时,该连续块中的灯将熄灭。你只能打开关闭的灯。为了最终关闭所有K灯,您需要打开的最小灯数是多少?
输入说明 第一行输入将由整数K组成,表示灯的数量。接下来的K行中的每一行将具有整数0(表示关闭的灯)或整数1(表示) 一盏明灯。
输出规范 您的程序应输出必须打开的最小灯数才能拥有 所有的K灯都关闭了。
示例输入1 五 1 1 0 1 1
样本输入1的输出 1
样本1的说明 请注意,打开第三个灯将创建五个连续的灯,这些灯将亮起 转动导致所有这五个灯都关闭。 注意:至少30%的测试用例的K≤10。
我不知道应该使用哪种算法来解决这个问题,因为似乎有太多的可能性。任何帮助将不胜感激,我理解python,c ++和java。
答案 0 :(得分:1)
在图表上看似shortest path problem,G=(V,E)
其中V={all light configurations}
和E={ (u,v) | moving from state u to state v by turning on some light}
。
这个问题可以通过一个简单的BFS来解决(因为图表没有加权),你可以使用bi-directional BFS来加快速度,因为你有一个目标节点。
我曾经解释过如何进行双向搜索的详细信息以及为什么different thread更好:
算法思路:同时从源和目标进行BFS搜索:[BFS直到两者中的深度1,直到两者中的深度2,....]。
当你找到一个顶点v时,算法将结束,它位于BFS的前面。
算法行为:终止算法运行的顶点v将恰好位于源和目标之间的中间位置。
这个算法在大多数情况下会产生更好的结果,然后从源头得到BFS [解释为什么它比BFS更好],并且肯定会提供答案,如果存在的话。
为什么它比源头的BFS更好?
假设源与目标之间的距离为k
,分支因子为B
[每个顶点具有B边缘]。
BFS将打开:1 + B + B^2 + ... + B^k
个顶点。
双向BFS将打开:2 + 2B + 2B^2 + 2B^3 + .. + 2B^(k/2)
顶点。
对于大B和k,第二个显然比第一个好得多。
注意,这个解决方案不需要将整个图形存储在内存中,它只需要实现一个函数:successor(v)
,它返回一个顶点的所有后继[你可以到达的所有顶点,距离v] 1步之内。这样,只应存储您打开[2 + 2B + ... + 2B^(k/2)
的节点,如上所述]。为了进一步节省内存,您可以从一个方向使用Iterative Deepening DFS,而不是BFS,但会消耗更多时间。
答案 1 :(得分:0)
我没有看到针对此的特定定向算法;我想我会把它视为动态编程问题。
初始活动集包含初始亮序列。
在每个后续步骤中,生成通过翻转一个开关可以到达的所有序列;一般情况下,你只需要翻转一个" on"旁边的开关。光。删除所有已经看过的序列。
一旦遇到"所有灯关闭"顺序,停止并返回当前步数(==您翻转开关的次数)。