一、问题描述
给玩家4张牌,每张牌牌面值在1~13之间,允许其中有数值相同的牌。采用加、减、乘、除四则运算,允许中间运算存在小数,并且可以使用括号,但每张牌只能使用一次,尝试构造一种表达式,使其运算结果为24.
如
输入:3 3 7 7
输出:(((3)/(7))+(3))*(7)
二、程序实现原理
遍历所有可能的组合,直到找到一个符合条件的组合或者遍历所有情况没有找到满足的组合,具体详见代码注释
三、程序基本实现
#include<iostream> #include<string> #include<cstdio> #define threshold 1E-6 #define num_count 4 #define resultv 24 using namespace std; double number[num_count]; //表达式结果暂存表 string result[num_count]; bool pointGame(int n){ // if(n==1){ //由于浮点数运算不能直接比较大小,因此采用阈值限制判断相等 if(abs(number[0]-resultv)<threshold){ cout<<result[0]<<endl; return true; }else{ return false; } } //对n(n>2)个元素,随机取两个元素,双重循环,取得所有两两组合 for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ double a,b; a=number[i]; b=number[j]; string expa,expb; expa=result[i]; expb=result[j]; /*当进行i,j位置两个元素的四则运算后,程序的规模有n变成了n-1(i,j两个元素合并成了一个元素) * 这n-1个元素包括去除i,j位置的值,在加上i,j计算的结果值 * 如何将这n-1个元素保存在前n-1个位置,以递归调用pointGame方法。 * 将最后位置(n-1)的元素,保存在j位置,将i,j之和保存在i位置。 */ number[j]=number[n-1]; result[j]=result[n-1]; //+运算 number[i]=a+b; result[i]="("+expa+")"+"+"+"("+expb+")"; if(pointGame(n-1)){ return true; } //-运算 number[i]=a-b; result[i]="("+expa+")"+"-"+"("+expb+")"; if(pointGame(n-1)){ return true; } number[i]=b-a; result[i]="("+expb+")"+"-"+"("+expa+")"; if(pointGame(n-1)){ return true; } // *运算 number[i]=a*b; result[i]="("+expa+")"+"*"+"("+expb+")"; if(pointGame(n-1)){ return true; } // /运算 number[i]=a/b; result[i]="("+expa+")"+"/"+"("+expb+")"; if(pointGame(n-1)){ return true; } number[i]=b/a; result[i]="("+expb+")"+"/"+"("+expa+")"; if(pointGame(n-1)){ return true; } number[i]=a; number[j]=b; result[i]=expa; result[j]=expb; } } return false; } int main(){ cout<<"please input four numbers:"<<endl; int a; for(int i=0;i<num_count;i++){ char ch[20]; cin>>a; number[i]=a; sprintf(ch,"%d",a); result[i]=ch; } if(pointGame(4)){ cout<<"成功"<<endl; }else{ cout<<"失败"<<endl; } system("pause"); return 0; }
高效方法待续。。。。。。