题意:给定你四个数,问你用乘,加,减,还有连接,四种方法可以组合成多少种不同的答案,注意连接必须和其他的操作混在一起使用。
思路:用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;
}