2020 ICPC Asia Taipei-Hsinchu Regional B - Make Numbers (乱搞)

在这里插入图片描述
题意:给定你四个数,问你用乘,加,减,还有连接,四种方法可以组合成多少种不同的答案,注意连接必须和其他的操作混在一起使用。

思路:用next_permutation生成全排列后,用dfs用枚举他们的组合形式,把加减作为最后的方法。
参考别人的代码实现的,学习一下大佬的写法。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e4 + 7;
int ans,vis[MAXN];//vis记录答案
map<pair<vector<int>,int>,int>mp;//记录当前的序列是否重复出现过

void dfs(vector<int>vec,int op){
	if(mp[{vec,op}]) return ;//出现过直接返回
	mp[{vec,op}]++;
	int siz = vec.size();
	if(siz == 1){//满足题目的条件
		if(!vis[vec[0]] && vec[0] >= 0) ans++,vis[vec[0]] = 1;
		// cout<<ans<<endl;
		return ;
	}
	if(op == 3){//最低的优先级 + 和 -
		vector<int>t;
		t.push_back(vec[0] + vec[1]);
		for(int i = 2;i < siz;i ++) t.push_back(vec[i]);
		dfs(t,op);//去枚举他们之间的+ 与 -的关系

		t[0] = vec[0] - vec[1];//换成-

		dfs(t,op);
	}
	if(op == 1 || op == 2){//因为* 和 连在一起的优先级高
		dfs(vec,op+1);//去做加和减操作
		if(siz == 2 && op == 1) return ;//两个数之间得到答案不能直接连 例如样例没有 1121 这个数
		for(int i = 0;i < siz - 1;i ++){//枚举把当前的数字分成几块
			vector<int>t;
			for(int j = 0;j < i;j ++) t.push_back(vec[j]);//放前面的
			if(op == 2){//代表乘法 依次在他们之间填乘法
				t.push_back(vec[i] * vec[i+1]);
			}
			else if(op == 1){//代表连在一起
				t.push_back(vec[i+1] >= 10 ? vec[i]*100 + vec[i+1] : vec[i] * 10 + vec[i+1]);
			}
			for(int j = i + 2;j < siz;j ++) t.push_back(vec[j]);//放后面的
			dfs(t,op);
		}
	}
} 

int main(){
	
	vector<int>vec;
	int x;
	for(int i = 1;i <= 4;i ++) scanf("%d",&x),vec.push_back(x);
	sort(vec.begin(),vec.end());
	do{
		dfs(vec,1);
		// cout<<ans<<endl;
	}while(next_permutation(vec.begin(),vec.end()));//生成全排列
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值