使用加法,减法和连接将数字组合到给定数字的方法

时间:2017-11-22 11:49:01

标签: c++ algorithm

我通过蛮力以自己的方式检查所有组合来解决这个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;?

3 个答案:

答案 0 :(得分:1)

所有这些挑战的诀窍不是两次做同样的工作。也就是说,12345678-912345678+912345678 * 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;
}