我使用这个算法来划分(1<<N)-1,给定N。这是代码:
void btrack(int k, int N, int sum, int used, int rep) {
//if (k > (N + 1)) exit(-1);
//printf("called with k = %d, N = %d, sum = %d, used = %d, rep = %d\n", k, N, sum, used, rep);
if (sum == (1 << N) - 1) {
printf("ended with %d \n", rep);
return;
}
if ((sum > (1 << N) - 1) || (used & 1 << k))
return;
used |= (1 << k);
for (int i = 1; i <= (1 << N) - 1; i++) {
if (!(used & 1 << i))
btrack(i, N, sum + i, used, rep * 10 + i);
}
}
字符串
我不想要一个常规分区。分区中的数字必须是唯一的。快速示例:
N = 3 -> (1<<N)-1 = 7
the Valid answers are :
1 + 2 + 4 = 7
2 + 5 = 7
6 + 1 = 7
4 + 3 = 7
7 = 7
the likes of :
2 + 2 + 2 + 1 = 7
1 + 1 + 1 + 1 + 3 = 7
etc...
are all incorrect because some numbers are repeated
型
我以为我实现了这个逻辑,但结果令人失望。我有时得到的总和大于目标,和重复。rep
变量将保存用于求和的数字:1+2+3
的123
或2+5
的25
谢谢你
2条答案
按热度按时间8iwquhpp1#
存在一些问题:
rep * 10 + i
只能存储个位数。对于N=4
,您不能表示1+15
或2+14
等。used |= (1 << k);
受int
类型的范围限制。对于大于4
的N
,k
可以大于30,因此1 << k
将具有未定义的行为。你的方法可能适用于
N < 4
,但对于更大的值需要更通用的方法。我建议使用数组。这个数组最多需要保存sqrt(1 << N)
数字,因此1 << (N - 1)
数字。v440hwme2#
你错误地使用了变量
k
。这似乎是你试图测试的最后一个值。递归的本质是你试图把问题分解成更小的问题,所以如果你想避免重复,那么你永远不应该在递归调用中使用相同的值。相反,开始在
k+1
处开始循环:字符串
输出量:
型
现在,这一切都可以工作,直到你需要分区非常大的值。你的基数为10的
rep
值几乎立即变得无用,而你的used
值用完了位。当你想真正 * 打印 * 一个结果时,你需要搜索一个由大部分零组成的位数组。另一种解决方案是将路径存储在数组中。它可能看起来像这样(半健壮但有点天真):
型
输出量:
在这里,一个数组被用来存储当前值的路径,递归调用试图通过只使用比上次使用的值大的值来从剩余的值中构建一个值。这会使用更多的内存,但性能应该会更好。
请注意,由于数组本质上是一个堆栈,因此您可能完全不需要递归就可以实现此解决方案,只需额外注意一点。这是一个完美的 “读者练习”。