问题:
给玩家4张牌,每张牌的面值在1-13之间,允许其中有数值相同的牌,采用加、减、乘、除四则运算,允许中间运算存在小数,并且可以使用括号,但每张牌只能用一次。构造表达式,使其结果为24。
给玩家4张牌,每张牌的面值在1-13之间,允许其中有数值相同的牌,采用加、减、乘、除四则运算,允许中间运算存在小数,并且可以使用括号,但每张牌只能用一次。构造表达式,使其结果为24。
解题思路:穷举、回溯。设数字集合为A,每次从A中任取出2个数,穷举进行4种运算(+,-,*,/),将运算结果放入A中,直到最后A中剩下一个数。
用覆盖的方法来剔除取出的2个数,值得学习!!
参考书中的代码:
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> using namespace std; const double bound=1e-6; //浮点数运算存在误差 string str[5]; double num[5]; int f(int n) { if(n==1) { if(fabs(num[1]-24)<bound) { cout<<str[1]<<endl; return 1; } else return 0; } for(int i=1;i<n;i++) { for(int j=i+1;j<=n;j++) { double a=num[i]; double b=num[j]; string t1,t2; t1=str[i]; t2=str[j]; //覆盖掉用过的数 num[j]=num[n]; str[j]=str[n]; num[i]=a+b; str[i]='('+t1+'+'+t2+')'; if(f(n-1)) return 1; num[i]=a*b; str[i]='('+t1+'*'+t2+')'; if(f(n-1)) return 1; num[i]=a-b; str[i]='('+t1+'-'+t2+')'; if(f(n-1)) return 1; num[i]=b-a; str[i]='('+t2+'-'+t1+')'; if(f(n-1)) return 1; if(b!=0) { num[i]=a/b; str[i]='('+t1+'/'+t2+')'; if(f(n-1)) return 1; } if(a!=0) { num[i]=b/a; str[i]='('+t2+'/'+t1+')'; if(f(n-1)) return 1; } num[i]=a; num[j]=b; str[i]=t1; str[j]=t2; } } return 0; } int main() { for(int i=1;i<=4;i++) { cin>>num[i]; //itoa函数只能用 char[]做参数 char buf[30]; itoa(num[i],buf,10); str[i]=buf; } f(4); system("pause"); return 0; }