2022-01-13 20:52:15
thumb_up 0
模拟大题
模拟赛没人的碰题,不简单
前言:为了表达,一下将类似于“(((3+5)+2)+7)”的东西称作“形式化”
思路: 在枚举全排列时做关于运算操作,两两合并,枚举四种运算答案与形式
难点:
(1)怎样保存在搜索时的“形式化”答案?
(2)两两合并后的回溯问题
(3)字典序问题
解决:
(1)在合并时顺便处理“形式化”的答案
(2)不妨将前后化成一样的赋值方法,类似于:
1.令a[1]为第一个数,那么易得两两合并与原四个数个数的和为7,因为4
个数两两合并会产生4+4-1=7个数
2.答案在a[7]
3.因为是直接赋值所以不用回溯
(3)取库里的min,字符串大小比较标准就是字典序
形式化可以与a[7]的思路一样
0.代码:
#include<bits/stdc++.h>
using namespace std;
int a[10];
string ans,s[10];
bool v[10],g[10];
//s——形式化答案
void dfs(int k){
if(k==7){
if(a[7]==24)
{
if(ans == "") ans = s[7];//7是答案
ans=min(ans,s[7]);
}
return;
}
for(int i=1;i<=k;i++)//到k是因为每次操作会多一个数
{
if(!v[i]){
v[i]=true;
for(int j=1;j<=k;j++)
{
if(i==j) continue;//合并i,j两个数值
if(!v[j]){//基本全排列判重
v[j]=true;//标记
a[k+1]=a[i]+a[j]//数值处理;
s[k+1]="("+s[i]+"+"+s[j]+")";//形式化处理
dfs(k+1);
a[k+1]=a[i]-a[j];
s[k+1]="("+s[i]+"-"+s[j]+")";
dfs(k+1);
a[k+1]=a[i]*a[j];
s[k+1]="("+s[i]+"*"+s[j]+")";
dfs(k+1);//同上
if(a[j] != 0)//被除数不为0
if(a[i]%a[j]==0){//能整除
s[k+1]="("+s[i]+"/"+s[j]+")";
a[k+1]=a[i]/a[j];
dfs(k+1);
}
v[j]=false;//回溯
}
}
v[i]=false;
}
}
}
int main()
{
for(int i=1;i<=4;i++) cin >> a[i];
for(int i=1;i<=4;i++) s[i]+=char(a[i]+48);//形式化s[1-4]先与a[1-4]相同
dfs(4);//先是枚举(1~4的合并)
cout << ans;
return 0;
}