【发布时间】:2017-03-13 21:18:06
【问题描述】:
我有一项任务我已经坚持了太久。我应该像这样考虑从 1 到 N 的所有可能表达式:
n = 5;
1 % 2 % 3 % 4 % 5 = ?
其中 % 可以是加法、减法或乘法(+、-、*) 我要做的是考虑这些操作的所有可能组合,并计算有多少结果表达式等于 n 本身。
因此,例如,对于 n=4,答案是 1,因为只有一个表达式等于 n。
1 + 2 - 3 + 4 = 4
对此还有一些注意事项 - 乘法的绑定比其他两个操作更强。比如
1 + 2 + 3 * 4 * 5 + 6
需要解析为
1 + 2 + (3 * 4 * 5) + 6
此外,乘法最多只能连续使用 5 次(不是总共),因此 n=20 以下的任何内容都可以放入整数。 为了解决这个问题,我编写了这个递归树,但是在 n=15 等更高的值时,我的输出会变得不正确。
[N ] - [Expected result] [My program's result]
[5 ] - [ 3] [ 3]
[6 ] - [ 1] [ 1]
[9 ] - [ 27] [ 27]
[15] - [ 3932] [ 3911]
[16] - [ 9803] [ 9327]
[17] - [ 23209] [ 22942]
我已经尝试诊断此问题将近一周,但无法使其正常工作...我尝试使代码尽可能可读,并在必要时发表评论。只是为了解释代码的作用——它构建了一个树,其中 (+,- 和 *) 是每次迭代的分支。每个节点都是直到那个点的表达式的总和,所以当我们达到 depth = n 时,所有的结束节点都是可能的表达式总和——我们要做的就是检查它们是否等于 n。如下图:
#include <stdio.h>
int n;
int result = 0;
void tree(int depth, int sum, int mul, int last) {
//DEPTH = recursion from 1 to n
//SUM = the sum of the expression
//MUL = counter to track how many consecutive multiplications have been done
//LAST = previous number added to sum
//if n nodes reached
if (depth == n) {
if (sum == n) {
//count result
result++;
}
return;
}
//build tree
depth++;
if (mul % 5 != 0) { //if multiplication hasn't been used 5x in a row
tree(depth, (sum - last) + (last * depth), mul + 1, last * depth);
} else {
//else dont build a multiplication branch, but reset the counter
mul = 1;
}
//build addition and subtraction trees
tree(depth, sum + depth, mul, depth);
tree(depth, sum - depth, mul, depth * -1);
}
int main(int argc, char **argv) {
scanf("%i", &n);
tree(1, 1, 1, 1);
printf("%i\n", result);
return 0;
}
更新 1:MUL 计数器已更正
#include <stdio.h>
int n;
int result = 0;
void tree(int depth, int sum, int mul, int last) {
//DEPTH = recursion from 1 to n
//SUM = the sum of the expression
//MUL = counter to track how many consecutive multiplications have been done
//LAST = previous number added to sum
//if n nodes reached
if (depth == n) {
if (sum == n) {
//count result
result++;
}
return;
}
//build tree
depth++;
if (mul < 5) { //if multiplication hasn't been used 5x in a row
tree(depth, (sum - last) + (last * depth), mul + 1, last * depth);
} else {
//else dont build a multiplication branch, but reset the counter
mul = 0;
}
//build addition and subtraction trees
tree(depth, sum + depth, mul, depth);
tree(depth, sum - depth, mul, depth * -1);
}
int main(int argc, char **argv) {
scanf("%i", &n);
tree(1, 1, 0, 1);
printf("%i\n", result);
return 0;
}
更改:根据答案更正了计数器和起始值(谢谢!),但程序仍然在高值时产生不正确的结果,更新数据:
[N ] - [Expected result] [My program's result]
[5 ] - [ 3] [ 3]
[6 ] - [ 1] [ 1]
[9 ] - [ 27] [ 27]
[15] - [ 3932] [ 3924]
[16] - [ 9803] [ 9781]
[17] - [ 23209] [ 23121]
结果更接近了!!
【问题讨论】:
-
主题:这不是通常所说的树。它只是一个递归函数调用。
-
我刚刚意识到我的逻辑中的错误 - 我在加法和减法分支中传递了 mul (没有递增),而我应该一直将它们重置为 0 ......现在很明显。非常感谢!!!
-
还有一个bug:你应该在递归加减法时传递
0,但只有在你没有递归乘法时才将mul重置为0。这是不正确的。 -
如果忽略超过 5 个连续乘法的组合,您将不会得到正确的结果。
-
Don't put "solvedThank you..." 你有 3 个答案,你可以接受其中一个答案,也可以写下自己的答案并接受。