2011年加拿大计算机竞赛:您需要打开的最小灯数是多少? (编程算法)

时间:2015-02-09 19:11:03

标签: algorithm

我在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。

2 个答案:

答案 0 :(得分:1)

在图表上看似shortest path problemG=(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"旁边的开关。光。删除所有已经看过的序列。

一旦遇到"所有灯关闭"顺序,停止并返回当前步数(==您翻转开关的次数)。