Algorithm 查找关闭灯的最小按压次数

Algorithm 查找关闭灯的最小按压次数,algorithm,Algorithm,我试图解决一个编程问题,但我的计算机无法找到一个有效的算法。情况是这样的:我们有一组n灯,它们可以打开(1)或关闭(0)如下:111000101101。该字节字符串表示有13个灯组成一个圆圈,其中前三个灯点亮,然后3个下一个灯熄灭,依此类推,圆圈表示最后一个灯紧靠第一个灯 然后我们得到了一个整数m>0。这意味着我们可以在任何时候选择一个灯,然后它和它的m相邻的灯将其状态s更改为1-s。即,如果m=2且灯状态为1110001011101,则将该过程应用于第一个灯,我们得到序列00000010111

我试图解决一个编程问题,但我的计算机无法找到一个有效的算法。情况是这样的:我们有一组
n
灯,它们可以打开
(1)
或关闭
(0)
如下:
111000101101
。该字节字符串表示有
13个
灯组成一个圆圈,其中前三个灯点亮,然后
3个
下一个灯熄灭,依此类推,
圆圈
表示最后一个灯紧靠第一个灯

然后我们得到了一个整数
m>0
。这意味着我们可以在任何时候选择一个灯,然后它和它的
m相邻的
灯将其状态
s更改为1-s
。即,如果
m=2
且灯状态为
1110001011101
,则将该过程应用于第一个灯,我们得到序列
0000001011110


现在的问题是,如果关于
2200
m
关于
110
的长度字符串是固定的,那么如何开发
算法
,以
最小
圈数关闭所有灯,您的解释没有明确说明灯是否只应关闭或“翻转”(即,0变为1,1变为0)。您的示例数据只是将其关闭

如果是这种情况,只需将110个灯设置为0-这将比在关闭它们之前查询它们的状态更快。假设您的灯位于称为“灯”的阵列中,且启动灯位置为startPos:

// These first 2 lines added after Kolmar remark about adjacent lamps meaning lamps to the left and right.
startPos = startPos - m;
if (startPos < 0) startPos += lamps.length; 
for (int i=0; i <= m + 1; i++){
  if ((i + startPos) > lamps.length) startPos = 0;
  lamps[i + startPos] = 0;
}

使用Z/2Z上的线性代数(即仅包含数字0和1的字段)可以解决此类翻转问题

假设有N个灯泡和N个开关。假设M是一个N乘N矩阵,如果按下开关i切换灯泡j,位置i,j中有1。在这里,当N=5,m=1时,矩阵将如下所示:

1, 1, 0, 0, 1
1, 1, 1, 0, 0
0, 1, 1, 1, 0
0, 0, 1, 1, 1
1, 0, 0, 1, 1
设x为大小为N的列向量,其中每个条目为0或1

然后Mx(即矩阵M和向量x除以Z/2Z的乘积)是大小为N的列向量,它是按下x中1s对应的开关的结果。这是因为在Z/2Z中,乘法类似于“and”,加法类似于“xor”


设v为大小为N的列向量,如果灯泡i最初点亮,则v_i=1。如果是线性系统Mx=v的解,那么x就解决了这个问题。例如,可以使用高斯消去法来解决此问题。

此问题类似于众所周知的“熄灯”问题。一种方法是使用线性代数。用较小的数字更容易理解,比如长度=5和m=1

首先要注意的是,选择一盏灯并两次更改它(及其邻居)的状态没有任何效果。第二,请注意,灯(及其相邻灯)的开关顺序并不重要。因此,战略只是一组指示灯。我们将用1表示选择作为策略一部分的灯,用0表示未选择的灯。我们将1和0放在列向量中,例如,
(01101)^T
,其中T表示转置(行变为列)。该策略意味着在位置1(当然从位置0开始)及其两个相邻位置切换灯;然后是位置2的灯及其两个邻居,最后是位置4的灯及其两个邻居

策略的效果可以通过域GF(2)上的矩阵乘法来计算。GF(2)只有两个元素,
0
1
,除了规则
1+1=0
之外,还有普通的算术规则。然后,上述策略的效果是矩阵与矩阵相乘的结果,其结果是在
i-th
列中选择lamp
i
,换句话说,通过如下“循环矩阵”:

[ 1 1 0 0 1 ] [0]   [0]
[ 1 1 1 0 0 ] [1]   [0]
[ 0 1 1 1 0 ] [1] = [0]
[ 0 0 1 1 1 ] [0]   [0]
[ 1 0 0 1 1 ] [1]   [1]
策略
(0 1 0 1)^T
的结果是只切换最后一个位置的灯。因此,如果您只启动最后一个位置的灯并应用该策略,则所有灯都将熄灭

在这个简单的例子中,我们用列向量
b
表示初始配置。然后,解决方案是满足矩阵方程
Ax=b
的列向量
x

现在的问题是,对于给定的
b
,1)是否有一个x满足
Ax=b
?2)解
x
唯一吗?如果不是,哪个
x
1
最小?3)如何计算

上述问题的答案将取决于手头特定问题的数字“length”和“m”。在上面考虑的length=5,m=1问题中,线性代数理论告诉我们,任何
b
都有唯一的解。我们可以得到
形式的
b
的解(0…1…0)^T
,也就是说,通过“旋转”解,一个1和其余的0
(0 1 1 0 1)^T
。我们可以将任何解唯一地表示为这些解的线性组合,因此具有最小1个数的策略/解与任何给定初始状态的唯一解相同

另一方面,当长度=6和m=1时,所有三种策略
(100100)^T
(010010)^T
,和
(001001)^T
都映射到结果
(111111)^T
,因此在某些情况下没有唯一的解;根据线性代数理论,在某些其他情况下没有解

通常,我们可以使用高斯消去法判断解是否存在且唯一。在上述5x5情况下,将第0行添加到第1行和第4行

[ 1 1 0 0 1 ] [1 0 0 0 0]    [ 1 1 0 0 1 ] [1 0 0 0 0]
[ 1 1 1 0 0 ] [0 1 0 0 0]    [ 0 0 1 0 1 ] [1 1 0 0 0]
[ 0 1 1 1 0 ] [0 0 1 0 0] -> [ 0 1 1 1 0 ] [0 0 1 0 0] ->
[ 0 0 1 1 1 ] [0 0 0 1 0]    [ 0 0 1 1 1 ] [0 0 0 1 0]
[ 1 0 0 1 1 ] [0 0 0 0 1]    [ 0 1 0 1 0 ] [1 0 0 0 1]
然后交换第1行和第2行;然后将第1行添加到第0行和第4行

[ 1 1 0 0 1 ] [1 0 0 0 0]    [ 1 0 1 1 1 ] [1 0 1 0 0]
[ 0 1 1 1 0 ] [0 0 1 0 0]    [ 0 1 1 1 0 ] [0 0 1 0 0]
[ 0 0 1 0 1 ] [1 1 0 0 0] -> [ 0 0 1 0 1 ] [1 1 0 0 0] ->
[ 0 0 1 1 1 ] [0 0 0 1 0]    [ 0 0 1 1 1 ] [0 0 0 1 0]
[ 0 1 0 1 0 ] [1 0 0 0 1]    [ 0 0 1 0 0 ] [1 0 1 0 1]
然后将第2行添加到第0、1、3、4行;然后将第3行添加到第1、2行

[ 1 0 0 1 0 ] [0 1 1 0 0]    [ 1 0 0 0 0 ] [1 0 1 1 0]
[ 0 1 0 1 1 ] [1 1 1 0 0]    [ 0 1 0 0 1 ] [0 0 1 1 0]
[ 0 0 1 0 1 ] [1 1 0 0 0] -> [ 0 0 1 0 1 ] [1 1 0 0 0] ->
[ 0 0 0 1 0 ] [1 1 0 1 0]    [ 0 0 0 1 0 ] [1 1 0 1 0]
[ 0 0 0 0 1 ] [0 1 1 0 1]    [ 0 0 0 0 1 ] [0 1 1 0 1]
最后将第4行添加到第1、2行:

[ 1 0 0 0 0 ] [1 0 1 1 0]
[ 0 1 0 0 0 ] [0 1 0 1 1]
[ 0 0 1 0 0 ] [1 0 1 0 1]
[ 0 0 0 1 0 ] [1 1 0 1 0]
[ 0 0 0 0 1 ] [0 1 1 0 1]
您可以在右矩阵的列中读取解决方案的基础。例如,我们上面使用的解决方案位于右矩阵的最后一列

你应该试着用高斯消去法
[ 1 0 0 0 0 ] [1 0 1 1 0]
[ 0 1 0 0 0 ] [0 1 0 1 1]
[ 0 0 1 0 0 ] [1 0 1 0 1]
[ 0 0 0 1 0 ] [1 1 0 1 0]
[ 0 0 0 0 1 ] [0 1 1 0 1]