Algorithm 按照一些规则查找3x3矩阵中的所有组合

Algorithm 按照一些规则查找3x3矩阵中的所有组合,algorithm,matrix,Algorithm,Matrix,给定3x3矩阵: |1 2 3| |4 5 6| |7 8 9| 我想通过按照以下规则连接此矩阵中的数字来计算所有组合: 组合宽度介于3和9之间 只使用一个数字一次 您只能连接相邻的号码 一些示例:123、258、2589、123654等 例如,1238不是一个好的组合,因为3和8不是相邻的。123和321的组合不同。 我希望我的描述清楚。 如果有人有任何想法,请告诉我。事实上,我不知道如何开始:D。谢谢这是一个搜索问题。您可以使用直接的深度优先搜索和递归编程来快速解决问题。如

给定3x3矩阵:

|1 2 3|  
|4 5 6|  
|7 8 9|  
我想通过按照以下规则连接此矩阵中的数字来计算所有组合:

  • 组合宽度介于3和9之间
  • 只使用一个数字一次
  • 您只能连接相邻的号码
一些示例:123、258、2589、123654等
例如,1238不是一个好的组合,因为3和8不是相邻的。123和321的组合不同。
我希望我的描述清楚。

如果有人有任何想法,请告诉我。事实上,我不知道如何开始:D。谢谢这是一个搜索问题。您可以使用直接的深度优先搜索和递归编程来快速解决问题。如下所示:

func search(matrix[N][M], x, y, digitsUsed[10], combination[L]) {
    if length(combination) between 3 and 9 {
       add this combination into your solution
    }

    // four adjacent directions to be attempted
    dx = {1,0,0,-1}
    dy = {0,1,-1,0}
    for i = 0; i < 4; i++ {
       next_x = x + dx[i]
       next_y = y + dy[i]
       if in_matrix(next_x, next_y) and not digitsUsed[matrix[next_x][next_y]] {
           digitsUsed[matrix[next_x][next_y]] = true
           combination += matrix[next_x][next_y]
           search(matrix, next_x, next_y, digitsUsed, combination)

           // At this time, sub-search starts with (next_x, next_y) has been completed.
           digitsUsed[matrix[next_x][next_y]] = false
       }
   }
}
func搜索(矩阵[N][M],x,y,数字[10],组合[L]){
如果长度(组合)介于3和9之间{
将此组合添加到您的解决方案中
}
//尝试四个相邻方向
dx={1,0,0,-1}
dy={0,1,-1,0}
对于i=0;i<4;i++{
下一步x=x+dx[i]
下一个y=y+dy[i]
如果在矩阵中(下一个x,下一个y)且未使用数字[matrix[next x][next y]]{
digitsUsed[matrix[next_x][next_y]]=true
组合+=矩阵[next_x][next_y]
搜索(矩阵、下一个x、下一个y、使用的数字、组合)
//此时,子搜索开始于(下一个x,下一个y)已完成。
digitsUsed[matrix[next_x][next_y]]=false
}
}
}
因此,您可以对矩阵中的每个网格运行搜索函数,并且解决方案中的每个组合都是不同的,因为它们从不同的网格开始


此外,我们不需要记录表示矩阵中的一个网格已被或未被遍历的状态,因为每个数字只能使用一次,因此,已经遍历的网格将永远不会再被遍历,因为它们的数字已经包含在组合中。

在Python 3中,作为递归深度优先探索,这里有一个可能的实现:

def find_组合(数据、最小长度、最大长度):
#布尔矩阵,指示使用了哪些值
visited=[[False for uu in row]for row in data]
#当前组合
梳=[]
#在每个可能的位置启动递归算法
对于范围内的i(len(数据)):
对于范围内的j(len(数据[i]):
#添加初始组合元素并标记为已访问
comb.append(数据[i][j])
访问[i][j]=正确
#启动递归算法
查找组合的收益率(数据、最小长度、最大长度、访问、梳、i、j)
#与当前元素的所有组合生成后,将其移除
访问[i][j]=错误
comb.pop()
def查找组合记录(数据、最小长度、最大长度、访问、梳、i、j):
#如果当前组合的大小正确,则生成该组合
如果min_length=len(数据)或j2<0或j2>=len(数据[i2])或访问[i2][j2]:
持续
#添加邻居并标记为已访问
comb.append(数据[i2][j2])
已访问[i2][j2]=真
#为当前启动顺序生成组合
查找组合记录的产量(数据、最小长度、最大长度、访问量、梳、i2、j2)
#删除最后添加的组合元素
已访问[i2][j2]=错误
comb.pop()
#试试看
数据=[[1,2,3],
[4, 5, 6],
[7, 8, 9]]
最小长度=3
最大长度=9
对于查找组合中的梳(数据、最小长度、最大长度):
印刷品(c)
输出:

[1, 2, 3]
[1, 2, 3, 6]
[1, 2, 3, 6, 5]
[1, 2, 3, 6, 5, 4]
[1, 2, 3, 6, 5, 4, 7]
[1, 2, 3, 6, 5, 4, 7, 8]
[1, 2, 3, 6, 5, 4, 7, 8, 9]
[1, 2, 3, 6, 5, 8]
[1, 2, 3, 6, 5, 8, 7]
[1, 2, 3, 6, 5, 8, 7, 4]
[1, 2, 3, 6, 5, 8, 9]
[1, 2, 3, 6, 9]
[1, 2, 3, 6, 9, 8]
[1, 2, 3, 6, 9, 8, 5]
[1, 2, 3, 6, 9, 8, 5, 4]
[1, 2, 3, 6, 9, 8, 5, 4, 7]
...

查看所有组合,并选择连接的组合:

导入itertools
def坐标(n):
“”“矩阵中数字n的坐标。”“”
返回(n-1)//3,(n-1)%3
def(a、b):
“”“检查矩阵中a和b是否相邻。”“”
ai,aj=coords(a)
bi,bj=coords(b)
返回abs(ai-bi)+abs(aj-bj)==1
def已连接(梳状):
“”“检查组合是否已连接。”“”
返回所有(zip中a、b的相邻(a、b)(梳,梳[1:]))
对于范围(3,10)内的宽度:
对于itertools中的梳状排列(范围(1,10),宽度):
如果已连接(梳):
打印(梳子)

首先,我会查找递归,可能是广度或深度优先搜索,同时跟踪“访问”节点。或者,如果您可以使用clojure、scheme或prolog,则它们内置了基于约束的自动解算器。e、 你会在clojure找到很多数独解算的例子。谢谢@gus!这对我来说似乎很好,但我想用Swift编写这个算法(我在描述中没有提到,我的不好)。我的主要问题是,我没有得到这个
返回全部(zip中a,b的相邻(a,b)(comb,comb[1:])
代码行。我不懂Python,这一行太让人困惑了。我理解这个概念,但不知道这行是如何工作的,以及如何将它“翻译”成Swift。另一种说法是
all(相邻(comb[I],comb[I+1]),因为I在范围内(len(comb)-1))
。如果
comb
中相邻的每两个数字在矩阵中也相邻,则返回true。我不知道斯威夫特,但这句话可能不是最难翻译的。这里棘手的部分隐藏在
itertools.permutations
调用中,如果您在Swift中没有类似的东西,您必须自己实现它或使用不同的方法。