算法训练 According to Bartjens 字符串四则运算

46 篇文章 0 订阅
26 篇文章 0 订阅

题目链接      问题描述
  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;
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值