我的作业我已经被困了太久了。我应该考虑从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;
}
#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]
结果更接近!!
答案 0 :(得分:4)
我不确定这会解决所有问题,但这是一个错误。
此代码:
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;
}
错了。
首先,你从mul
开始为1.所以它将采用以下值的真分支:1,2,3,4
所以你总共得到4次乘法。
请改为尝试:
if (mul % 6 != 0) { //if multiplication hasn't been used 5x in a row
^
Notice...
tree(depth, (sum - last) + (last * depth), mul + 1, last * depth);
}
或更好 - 请勿使用%
- 只需使用<
if (mul < 5) { //if multiplication hasn't been used 5x in a row
^
Notice...
tree(depth, (sum - last) + (last * depth), mul + 1, last * depth);
}
并开始使用mul
等于0,即tree(1, 1, 0, 1);
。
答案 1 :(得分:2)
我看到的主要问题是您没有正确重置 mul 计数器。一旦你采用+或 - 分支,你必须重置它以允许5 连续的乘法。单个+或 - 打破该字符串。
所以,除了从 4386427 的答案重置(使用从零开始的答案;我希望你会发现它不那么令人困惑),你需要
tree(depth, sum + depth, 0, depth);
tree(depth, sum - depth, 0, depth * -1);
这些识别出多序列计数器当前为0。
答案 2 :(得分:2)
您的算法存在问题:
mul
计数器应从0
开始。
您应该使用if (mul < 5)
代替if (mul % 5 != 0)
当您递交给其他运营商时,您应该始终通过0
。
另请注意,建议避免使用全局变量,尤其是n
和result
这样简短而无意义的名称。最好使用传递指针的状态结构。
这是一个改进版本,可以从命令行获取参数并打印解决方案:
#include <stdio.h>
#include <stdlib.h>
struct state {
int n;
int result;
char ops[20];
};
void print_exp(struct state *sp, int depth, int sum) {
for (int i = 1; i < sp->n; i++) {
printf("%d %c ", i, sp->ops[i]);
}
printf("%d = %d\n", sp->n, sum);
}
void tree(struct state *sp, int depth,int sum, int mul, int last, char op) {
// 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
sp->ops[depth - 1] = op;
if (depth == sp->n) {
if (sum == sp->n) {
//count result
sp->result++;
print_exp(sp, depth, sum);
}
return;
}
depth++;
if (mul < 5) { //if multiplication hasn't been used 5x in a row
// recurse with a multiplication
tree(sp, depth, (sum - last) + (last * depth), mul + 1, last * depth, '*');
}
// recurse with addition and subtraction operators
tree(sp, depth, sum + depth, 0, depth, '+');
tree(sp, depth, sum - depth, 0, -depth, '-');
}
int main(int argc, char **argv) {
struct state s = { 0, 0, "" };
if (argc > 1)
s.n = strtol(argv[1], NULL, 0);
else
scanf("%i", &s.n);
tree(&s, 1, 1, 0, 1, '\0');
printf("%i\n", s.result);
return 0;
}