思路说明:
回溯的思想,5个数,先任意找2个数进行加减乘除,把这2个数运算后的结果当做一个数,按相同的方法搜下去 把4个数任取2个然后合并成3个,再继续搜下去
详细解释:
任意找两个数,两重for循环,得到所有可能情况 保存中间结果,在dfs函数里,新建立一个长度5的int数组,其中第0位保存中间结果 ,
其它依次保存选取两个数后剩下来的数 其中dfs时也要记录搜索的深度
易错点:
题意中说some of,即不用5个数全参与运算,所以从一个到5个,
只要计算出满足要求的值都是可以的 max的初始值设为-INF,在这个上面WA了好久,我问了师父才明白,
参与运算后,虽然tar>=0,但是比tar小的运算结果不一定能够达到0或者-1一般的初始化值
个人历程:
这一题一开始感觉用枚举,受了之前做的题目的影响,感觉就5个数,枚举一下顺序,操作数,优先级应该就可以了,
写起代码来又很繁琐,多重循环到想吐,磕磕碰碰写出来,速度自己都看不下去,看了一位师兄的题解,又是搜索,本来像这种计算表达式的值,
用栈比较好,可是操作数的顺序是变化的,我感觉不太好处理,中间结果又如何区别也是要考虑的问题
参考代码:
#include<iostream>
#include<stack>
using namespace std;
int a[5];
int _max=0;//记录小于等于target的运算出的最大值
int tar;
bool flag;
int add(int a,int b){return a+b;}
int sub(int a,int b){return a-b;}
int mul(int a,int b){return a*b;}
int div2(int a,int b)
{
if(a<b)
{
a=a+b;
b=a-b;
a=a-b;
}
if( b==0 || a%b!=0)
return -1;
return a/b;
}
void dfs( int index[],int size )
{
if(flag)
return;
if( index[0]<=tar && index[0]>_max )
{
_max=index[0];
if(_max==tar){
flag=true;
return ;
}
}
if(size==1)
return ;
int i,j,h,k;
int num[5];
for( i=0; i<size; i++ )
{
for( j=i+1; j<size; j++)
{
for( h=1,k=0; k<size; k++)
if( k!=i && k!=j)
num[h++]=index[k];
num[0]=add(index[i],index[j]);
dfs(num,size-1);
num[0]=sub(index[i],index[j]);
dfs(num,size-1);
num[0]=-num[0];
dfs(num,size-1);
num[0]=mul(index[i],index[j]);
dfs(num,size-1);
num[0]=div2(index[i],index[j]);
if(num[0]!=-1)
{
dfs(num,size-1);
}
}
}
}
int main()
{
int n,i,j;
cin>>n;
for( int s=0; s<n; s++)
{
for( i=0; i<5; i++)
cin>>a[i];
cin>>tar;
_max=-1;
flag=false;
for(i=0; i<5; i++){
if( a[i]<=tar && a[i]>_max )
{
_max=a[i];
}
}
dfs(a,5);
cout<<_max<<endl;
}
}