[英]All possible combinations(with repetition) as values in array using recursion
I'm trying to solve a problem in which I need to insert math operations(+/- in this case) between digits or merge them to get a requested number. 我正在尝试解决一个问题,我需要在数字之间插入数学运算(在这种情况下为+/-),或者将它们合并以获取所需的数字。
For ex.: 123456789 => 123+4-5+6-7+8-9 = 120
例如:
123456789 => 123+4-5+6-7+8-9 = 120
My concept is basically generating different combinations of operation codes in array and calculating the expression until it equals some number. 我的概念基本上是在数组中生成操作码的不同组合,然后计算表达式,直到等于某个数字。
The problem is I can't think of a way to generate every possible combination of math operations using recursion. 问题是我想不出一种使用递归生成数学运算的所有可能组合的方法。
Here's the code: 这是代码:
#include <iostream>
#include <algorithm>
using namespace std;
enum {noop,opplus,opminus};//opcodes: 0,1,2
int applyOp(int opcode,int x, int y);
int calculate(int *digits,int *opcodes, int length);
void nextCombination();
int main()
{
int digits[9] = {1,2,3,4,5,6,7,8,9};
int wantedNumber = 100;
int length = sizeof(digits)/sizeof(digits[0]);
int opcodes[length-1];//math symbols
fill_n(opcodes,length-1,0);//init
while(calculate(digits,opcodes,length) != wantedNumber)
{
//recursive combination function here
}
return 0;
}
int applyOp(int opcode,int x, int y)
{
int result = x;
switch(opcode)
{
case noop://merge 2 digits together
result = x*10 + y;
break;
case opminus:
result -= y;
break;
case opplus:
default:
result += y;
break;
}
return result;
}
int calculate(int *digits,int *opcodes, int length)
{
int result = digits[0];
for(int i = 0;i < length-1; ++i)//elem count
{
result = applyOp(opcodes[i],result,digits[i+1]);//left to right, no priority
}
return result;
}
The key is backtracking. 关键是回溯。 Each level of recursion handles a single digit;
每个递归级别都处理一个数字。 in addition, you'll want to stop the recursion one you've finished.
此外,您将要停止已完成的递归操作。
The simplest way to do this is to define a Solver
class, which keeps track of the global information, like the generated string so far and the running total, and make the recursive function a member. 最简单的方法是定义一个
Solver
类,该类跟踪全局信息(例如到目前为止生成的字符串和运行的总数),并使递归函数成为成员。 Basically something like: 基本上像这样:
class Solver
{
std::string const input;
int const target;
std::string solution;
int total;
bool isSolved;
void doSolve( std::string::const_iterator pos );
public:
Solver( std::string const& input, int target )
: input( input )
, target( target )
{
}
std::string solve()
{
total = 0;
isSolved = false;
doSolve( input.begin() );
return isSolved
? solution
: "no solution found";
}
};
In doSolve
, you'll have to first check whether you've finished ( pos == input.end()
): if so, set isSolved = total == target
and return immediately; 在
doSolve
,您必须首先检查是否已完成( pos == input.end()
):如果是,则设置isSolved = total == target
并立即返回; otherwise, try the three possibilities, ( total = 10 * total + toDigit(*pos)
, total += toDigit(*pos)
, and total -= toDigit(*pos)
), each time saving the original total
and solution
, adding the necessary text to solution
, and calling doSolve
with the incremented pos
. 否则,尝试三种可能性(
total = 10 * total + toDigit(*pos)
, total += toDigit(*pos)
和total -= toDigit(*pos)
),每次保存原始的total
和solution
,添加solution
所需的文本,然后用递增的pos
调用doSolve
。 On returning from the recursive call, if ! isSolved
从递归调用返回时,如果
! isSolved
! isSolved
, restore the previous values of total
and solution
, and try the next possibility. ! isSolved
,恢复total
和solution
的先前值,然后尝试下一种可能性。 Return as soon as you see isSolved
, or when all three possibilities have been solved. 看到
isSolved
或解决所有三种可能性后,立即返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.