我一直试图在组合中解决问题。我有一个矩阵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。
限制是你必须从任何一点移动到你的邻居,你必须从矩阵中的每个位置开始,即每一行,col。你可以一次移动一步,即右,左,上,下和两个对角线位置。检查if条件。 即 如果你的(0,0)你可以移动到(1,0)或(1,1)或(0,1),即三个邻居。 如果你在(2,2)你可以移动到八个邻居 等......
答案 0 :(得分:1)
为了消除重复,您可以将8位数序列转换为8位整数,并将它们放入哈希表中。
记忆可能是一个好主意。您可以为矩阵中的每个单元格记忆所有可能从中获得的长度为2-7的组合。向后:首先为每个单元格生成2位数的所有序列。然后基于3位数等。
UPDATE: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
答案 1 :(得分:0)
有很多方法可以做到这一点。通过每个组合是一个完全合理的第一种方法。这一切都取决于您的要求。如果你的矩阵很小,而且这个操作不是时间敏感的,那就没问题了。
我不是一个算法家伙,但我确信有一些非常聪明的方法可以让别人跟我发帖。
使用CamelCase时,中的,方法名称应以小写字符开头。
答案 2 :(得分:0)
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行,依此类推。这是你期待的吗?
答案 3 :(得分:0)
您可以将矩阵视为一维数组 - 无论在这里(逐行“放置”行)。对于一维数组,您可以编写一个函数(假设您应该打印组合)
f(i, n) prints all combinations of length n using elements a[i] ... a[last].
它应跳过从[i]到[i + k]的一些元素(对于所有可能的k),打印[k]并进行递归调用f(i + k + 1,n - 1)。