题目链接 问题描述
Bartjens教授十分在意算术——因为他比较传统。他决定给学生布置一些计算作业,并且不能使用电子设备。不幸的是,Bartjens教授的打印机实在是太旧了,不能和新的打印机兼容。打印出了题目后,教授发现所有的符号都丢失了!例如2100-100=,被打印成了2100100=。不过,数字和等号被正确的打印了。更糟糕的是,教授的试题原稿不见了。因此,他需要恢复出这些题原来的样子。如果答案是2000,那么2100100=可能是:
2100-100=
2*100*10+0=
2*100*10-0=
2*10*0100=
2*-100*-10+0=
Bartjen教授记得几点:
1.他写的数字没有前导零。例如2*10*0100=就是不可行的。
2.他写0的时候不会写多个0。例如2*1000+000=就是不可行的。
3.他只用二元运算符,不用取负。所以2*-100*-10+0=也不合法。
4.他只用+、-、*,不用/和括号。
5.这些算式按照正常的优先级顺序计算。
你需要帮助barjen教授恢复这些题目。你需要在算式中插入至少一个运算符,使得答案是2000。有多少种可能的算式呢?
#include <iostream>
#include <string>
#include <deque>
#include <algorithm>
#include <vector>
using namespace std;
const int RES = 2000, N = 15;
const string operators = "+-*";
vector<string> ans;
string s;
int n,p[N];//用p记录运算符号,0为没有运算符。
bool compute(){
deque<int> num,opt;
for(int i = 0, sum = 0; i <= n; i++){
if(p[i] || i == n){
num.push_back(sum);
if(!opt.empty() && opt.back()== 3 && num.size() >= 2){
int a = num.back(); num.pop_back();
int b = num.back(); num.pop_back();
num.push_back(a*b);
opt.pop_back();
}
if(i != n) opt.push_back(p[i]);
sum = 0;
}
sum = sum*10+s[i]-'0';
}
while(!opt.empty()){
int x = num.front(); num.pop_front();
int y = num.front(); num.pop_front();
if(opt.front() == 1) num.push_front(x+y);
else num.push_front(x-y);
opt.pop_front();
}
return RES == num.front();
}
void solve(int cur,int v){
if(cur == n){
if(compute()){
string ss;
for(int i = 0; i < n; i++){
if(p[i]) ss.append(1,operators[p[i]-1]);
ss.append(1,s[i]);
}
ss.append(1,'=');
ans.push_back(ss);
}
return;
}
if(v || cur == 0) solve(cur+1,v*10+s[cur]-'0');
if(cur!= 0 ){
for(int j = 1; j <= 3; j++ ){
p[cur] = j;
solve(cur+1,s[cur]-'0');
}
p[cur] = 0;
}
}
int main(int argc, char** argv) {
cin>> s;
n = s.length()-1;
solve(0,0);
if(!ans.size() || s == "2000="){
cout<< "IMPOSSIBLE\n";
}else{
sort(ans.begin(),ans.end());
for(int i = 0; i < ans.size(); i++)
cout<< ans[i] << '\n';
}
return 0;
}