我通过蛮力以自己的方式检查所有组合来解决这个c++
练习。我想知道是否有更好,更优雅和/或更短/更快的解决方案?
这里是翻译过的问题:("没有"指的是连接)
/*
Write a program that outputs the number of possible ways to:
Combine ascending digits 1...9 using +, -, and "nothing" to get the result of input x.
Example:
Input: 100
Output: 11
(That's because we have 11 ways to get 100:)
123 - 45 - 67 + 89 = 100
123 + 4 - 5 + 67 - 89 = 100
123 + 45 - 67 + 8 - 9 = 100
123 - 4 - 5 - 6 - 7 + 8 - 9 = 100
12 - 3 - 4 + 5 - 6 + 7 + 89 = 100
12 + 3 + 4 + 5 - 6 - 7 + 89 = 100
12 + 3 - 4 + 5 + 67 + 8 + 9 = 100
1 + 23 - 4 + 56 + 7 + 8 + 9 = 100
1 + 2 + 34 - 5 + 67 - 8 + 9 = 100
1 + 23 - 4 + 5 + 6 + 78 - 9 = 100
1 + 2 + 3 - 4 + 5 + 6 + 78 + 9 = 100
*/
这是我的解决方案:
#include<iostream>
using namespace std;
int power(int a, int n) {
int rez = 1;
for (int i = 0; i<n; i++) {
rez *= a;
}
return rez;
}
void makeCombo(int c, int C[]) {
int digit = 0;
while (c != 0) {
C[digit] = c % 3;
c /= 3;
digit++;
}
}
bool testCombo(int C[], int x) {
int a = 9;
int sum = 0;
int concatenator = 0;
int concatenation = 0;
for (int i = 0; i < 8; i++) {
if (C[7-i] == 0) {
concatenator += a*power(10,concatenation);
concatenation++;
} else if (C[7-i] == 1) {
sum += a*power(10,concatenation);
sum += concatenator;
concatenator = 0;
concatenation = 0;
} else if (C[7-i] == 2) {
sum -= a*power(10,concatenation);
sum -= concatenator;
concatenator = 0;
concatenation = 0;
}
a--;
}
sum += a*power(10,concatenation);
sum += concatenator;
return (sum == x);
}
int main() {
int x, count = 0;
cin >> x;
int combo = 0;
int C[8] = {0,0,0,0,0,0,0,0};
while (combo < power(3,8)) {
makeCombo(combo, C);
if (testCombo(C, x)) { count++; }
combo++;
}
cout << count << endl;
return 0;
}
我听说过可能有一个简短的递归解决方案,我想知道如何解决这个问题,和/或是否有一个更好的&#34;更好的&#34;解决方案,你怎么能看到它&#34;?
答案 0 :(得分:1)
所有这些挑战的诀窍不是两次做同样的工作。也就是说,12345678-9
,12345678+9
和12345678 * 10 + 9
都有相同的逻辑来评估12345678
。
有很多方法可以实现这一点,但递归解决方案足够合理。
答案 1 :(得分:1)
更新:这不是我的解决方案,而是我听说过的递归方法。比我最初的解决方案更快,非常优雅。
#include <iostream>
using namespace std;
int x;
int count(int n, int num, int sum) {
if (n == 9) { return sum + num == x; }
int next = n + 1;
int counter = 0;
counter += count(next, next, sum + num);
counter += count(next, -next, sum + num);
num *= 10;
if (num < 0)
num -= next;
else
num += next;
counter += count(next, num, sum);
return counter;
}
int main(int x) {
cin >> x;
cout << count(1, 1, 0) << endl;
return 0;
}
答案 2 :(得分:0)
在这里,您可以找到完整的递归样本:
我写了两个递归方法,
test_combo
- 评估组合
make_combo
- 生成组合
#include<iostream>
using namespace std;
//recursivly evaluate the combo.
int test_combo( const std::string& s, int sign)
{
size_t next_pos = s.find_first_of("+-");
int sum = sign * strtol(s.substr(0,next_pos).c_str(),0,0);;
if(next_pos == string::npos)
{
return sum;
}
else
{
char op = s[next_pos];
switch(op)
{
case '+':
sum+=test_combo(s.substr(next_pos+1),1);
return sum;
case '-':
sum+=test_combo(s.substr(next_pos+1),-1);
return sum;
}
}
}
//recursivly build the combo.
void make_combo(int n, const std::string& s )
{
if(n==10)
{
int sum=test_combo(s,1);
if(sum==100)
cout<<s<<"="<<sum<<endl;
}
else
{
char next_digit = '0'+n; //we have 3 options:
make_combo(n+1,s+next_digit); //append next digit with no op
make_combo(n+1,s+'+'+next_digit); //append next digit with + op
make_combo(n+1,s+'-'+next_digit); //append next digit with - op
}
}
int main()
{
make_combo(2,"1");//string always start with a '1'
return 0;
}