【发布时间】:2021-02-12 10:26:06
【问题描述】:
我正在尝试制作一个小程序来解决倒计时问题。基本上,给定一个数字n 和一个数字向量,如果n 可以通过简单的操作(例如加法、div、mult 和 subs)来构造,则问题输出。
不使用数字向量的所有元素是可以的,但每个数字最多只能使用一次。
我试图给程序的输入是一个带有反向波兰符号的字符串,所以我做了一个小函数来解决这种表达式。
这是我的代码:
#include <iostream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
bool is_number(const std::string& s) {
string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}
vector<string> parseInput(const string& expression) {
vector<string> parsedInp;
string current = "";
for (auto token : expression) {
if (isdigit(token)) {
current += token;
}
else if (token == ' ') {
if (current != "") {
parsedInp.push_back(current);
current = "";
}
}
else {
parsedInp.push_back(string(1, token));
}
}
return parsedInp;
}
double operateExpression(const vector<string>& parsedInp) {
stack<double> expression;
for (auto token : parsedInp) {
if (is_number(token)) {
expression.push(stod(token));
}
else {
double op1 = expression.top();
expression.pop();
double op2 = expression.top();
expression.pop();
if (token == "+") {
expression.push(op1 + op2);
}
if (token == "-") {
expression.push(op1 - op2);
}
if (token == "*") {
expression.push(op1 * op2);
}
if (token == "/") {
expression.push(op1 / op2);
}
}
}
return expression.top();
}
string getSolution(vector<string> inp, const int target) {
vector<string> op = { "+", "-", "*", "/", "" };
//TODO....
}
int main() {
string expression;
getline(cin, expression);
vector<string> parsedInp = parseInput(expression);
cout << operateExpression(parsedInp) << endl;
}
所以我的第一个直觉是创建向量的所有可能排列,然后尝试连接向量中的操作,但我现在面临的问题是我找不到简单的方法来做到这一点。我不能不小心将它连接起来,因为operateExpression 会失败,但我不想使用try 和catch 来解决这个问题。另外,我认为应该有更简单的方法。
基本上,问题在于我不知道为原始向量的所有子集和排列生成所有可能表达式的好方法。例如,如果我有 (2,5) 作为输入,则可能有以下表达式:
2 5 +
2 5 -
2 5 /
2 5 *
(还有以5 作为第一个参数的相同操作。
对于(2,5,4):
(以上所有加...)
(2 5 + 4 +)
(2 5 - 4 +)
...
以及上述的所有排列。
那么有没有更好的方法在这里写getSolution?
谢谢。
编辑:
输入示例:(100,4,17,9,3,2) 和 n = 37 -> 17 100 3 2 + / +(顺序无关紧要)
阅读本文
编辑2: 我添加了一个函数,该函数生成一个矩阵,其中包含向量的所有可能选择(有重复),如下所示:
void choices(const vector<int>& values, int& currentValue, vector<int>& currentSet, vector<vector<int>>& combinations) {
if (currentSet.size() < values.size()) {
for (auto i : values) {
if (i != currentValue) {
currentSet.push_back(i);
combinations.push_back(currentSet);
choices(values, i, currentSet, combinations);
currentSet.pop_back();
}
}
}
}
所以基本上问题现在减少到能够将所有可能的操作添加到矩阵中的这些条目中的每一个,这就是我迷失的地方。 我知道暴力破解是不好的,但我只对这 4 个操作和 6 个值感兴趣。 还有就是怕组合爆炸……
【问题讨论】:
-
您能提供一个输入示例吗?
-
@RiccardoPetraglia 完成
-
您可以使用
std::next_permutation创建容器的所有排列。 -
@Darhuuk but
std::next_permutation不关心重复,操作可以重复 -
@Norhther 但这不是你在问题中所说的。你说你的第一直觉是创造所有的排列,但你找不到一个简单的方法来做到这一点。请用尽可能多的信息扩展您的问题。此外,重复排列不会使生成的答案出错,只会使程序变慢。目前尚不清楚这是否是一个问题。