![](/img/trans.png)
[英]Finding all possible combinations with 1 element in each row of a 2D array
[英]All possible combinations of length 8 in a 2d array
我一直在尝试解决组合问题。 我有一个6X6矩阵,我试图在矩阵中找到长度8的所有组合。
我必须在每一行,每一列的位置上从一个邻居移到另一个邻居,并且编写了一个递归程序来生成组合,但是问题是它也会生成很多重复项,因此效率很低。 我想知道如何消除重复计算并节省时间。
int a={{1,2,3,4,5,6},
{8,9,1,2,3,4},
{5,6,7,8,9,1},
{2,3,4,5,6,7},
{8,9,1,2,3,4},
{5,6,7,8,9,1},
}
void genSeq(int row,int col,int length,int combi)
{
if(length==8)
{
printf("%d\n",combi);
return;
}
combi = (combi * 10) + a[row][col];
if((row-1)>=0)
genSeq(row-1,col,length+1,combi);
if((col-1)>=0)
genSeq(row,col-1,length+1,combi);
if((row+1)<6)
genSeq(row+1,col,length+1,combi);
if((col+1)<6)
genSeq(row,col+1,length+1,combi);
if((row+1)<6&&(col+1)<6)
genSeq(row+1,col+1,length+1,combi);
if((row-1)>=0&&(col+1)<6)
genSeq(row-1,col+1,length+1,combi);
if((row+1)<6&&(row-1)>=0)
genSeq(row+1,col-1,length+1,combi);
if((row-1)>=0&&(col-1)>=0)
genSeq(row-1,col-1,length+1,combi);
}
我也在考虑编写一个动态程序,基本上是通过记忆来递归的。 这是一个更好的选择吗? 如果是,那么我不清楚如何在递归中实现它。 我真的有办法走到尽头吗???
谢谢
编辑例如结果12121212、12121218、12121219、12121211、12121213。
限制是您必须从任何点移至邻居,必须从矩阵中的每个位置(即每一行,列)开始。 您可以一次移动一步,即向右,向左,向上,向下和两个对角线位置。 检查是否满足条件。 例如,如果您输入的是(0,0),则可以移动到(1,0)或(1,1)或(0,1),即三个邻居。 如果您的收入(2,2),您可以搬到八个邻居。
等等...
要消除重复,您可以将8位数字序列转换为8位整数,并将其放入哈希表中。
记忆化可能是一个好主意。 您可以为矩阵中的每个单元记忆所有可以从中获得的长度2-7的可能组合。 向后:首先为每个单元格生成所有2位数字的序列。 然后根据3位数字等
更新:Python中的代码
# original matrix
lst = [
[1,2,3,4,5,6],
[8,9,1,2,3,4],
[5,6,7,8,9,1],
[2,3,4,5,6,7],
[8,9,1,2,3,4],
[5,6,7,8,9,1]]
# working matrtix; wrk[i][j] contains a set of all possible paths of length k which can end in lst[i][j]
wrk = [[set() for i in range(6)] for j in range(6)]
# for the first (0rh) iteration initialize with single step paths
for i in range(0, 6):
for j in range(0, 6):
wrk[i][j].add(lst[i][j])
# run iterations 1 through 7
for k in range(1,8):
# create new emtpy wrk matrix for the next iteration
nw = [[set() for i in range(6)] for j in range(6)]
for i in range(0, 6):
for j in range(0, 6):
# the next gen. wrk[i][j] is going to be based on the current wrk paths of its neighbors
ns = set()
if i > 0:
for p in wrk[i-1][j]:
ns.add(10**k * lst[i][j] + p)
if i < 5:
for p in wrk[i+1][j]:
ns.add(10**k * lst[i][j] + p)
if j > 0:
for p in wrk[i][j-1]:
ns.add(10**k * lst[i][j] + p)
if j < 5:
for p in wrk[i][j+1]:
ns.add(10**k * lst[i][j] + p)
nw[i][j] = ns
wrk = nw
# now build final set to eliminate duplicates
result = set()
for i in range(0, 6):
for j in range(0, 6):
result |= wrk[i][j]
print len(result)
print result
有很多方法可以做到这一点。 进行每种组合都是一种完全合理的第一种方法。 这完全取决于您的要求。 如果矩阵很小,并且此操作对时间不敏感,那么就没有问题。
我不是一个真正的算法专家,但是我敢肯定,有人会在我后面发布一些非常聪明的方法。
另外,
在Java中
使用CamelCase时,方法名称应以小写字母开头。
int a={{1,2,3,4,5,6}, {8,9,1,2,3,4}, {5,6,7,8,9,1}, {2,3,4,5,6,7}, {8,9,1,2,3,4}, {5,6,7,8,9,1}, }
长度是指矩阵元素的组合之和,结果为8。
也就是说,要与行本身以及与其他行元素相加的元素8。
从第1行= {{2,6},{3,5},}开始,到第1行元素再加上第2行,依此类推。 那是您所期望的吗?
您可以将矩阵想像成一维数组-无论在这里(将行一一“放置”)。 对于一维数组,您可以编写类似的函数(假设您应该打印组合)
f(i, n) prints all combinations of length n using elements a[i] ... a[last].
它应该从a [i]到a [i + k]跳过某些元素(对于所有可能的k),打印a [k]并进行递归调用f(i + k + 1,n-1)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.