/* 给定四个数,计算这四个数(1-13)的'+','-','*','/'能不能得到24(占时只实现满足一种情况就打印) 方法:穷举法 思路:有两种方式,(1)"连贯式计算"(2)"分隔式计算" (1)连贯式计算、例如对于2+4*3+5的计算,2+4=6 => 6*3=18 => 18+5=23 (2+4)*3+5 (2)分隔式计算、例如对于2+4*3+5的计算,2+4=6 => 3+5=8 => 6*8=48 (2+4)*(3+5) calc_24()方法,用三个for循环对四个数进行排列,又用三个for对三个符号进行循环, 因为符号可以重复,所以每个符号都有四种选择。调用calc_consecutive方法和cale_separate 方法判断是否为24. calc_consecutive()方法,计算连贯式的结果,就是每两个两个的计算,从左向右 cale_separate()方法,计算分隔式的结果,就是先前两个的结果,然后后两个,最后一起的结果。 这两上方法都会调用calc()方法,来计算两个数的结果,要对结果进行判断,比如相减的结果要 大于0,相除时,除数不能为0,并且不能有余数。 add_parenthesis()方法是加括号 get_consecutive_exp()方法对连贯式加括号,因为我们是用0,1,2,3,分别表示“+”,"-","*","/" 所以if(oper[0]<2 && oper[1]>=2)这句话是判断第一个操作符是"+"或"-",然后第二个操作符是"*"或"/", 因为第二个操作符的优先级比较高,所以前两个数字要加括号 get_separate_exp()方法是对分隔式加括号,这种比较简单,直接前两个,后两个加括号就可以了 */ #include <stdio.h> #include <iostream> #include <sstream> #include <string> using namespace std; char operator_char_def[4]={'+','-','*','/'}; int count=0; int calc(int n1,int n2,char oper) { if(oper<0 || oper>4) return -1; switch(operator_char_def[oper]) { case '+': return n1+n2; case '-': if(n1<n2) return -1; return n1-n2; case '*': return n1*n2; case '/': if((n2==0)||(n1%n2!=0)) return -1; return n1/n2; } return -1; } int calc_consecutive(int n[4],char oper[3]) { int r1 = calc(n[0],n[1],oper[0]); if(r1<0) return 0; int r2 = calc(r1,n[2],oper[1]); if(r2<0) return 0; int r = calc(r2,n[3],oper[2]); return r; } int cale_separate(int n[4],char oper[3]) { int r1 = calc(n[0],n[1],oper[0]); if(r1<0) return 0; int r2 = calc(n[2],n[3],oper[2]); if(r2<0) return 0; int r = calc(r1,r2,oper[1]); return r; } void tmp_output(int method,int n[4],char oper[3]) { cout<<((method==1)?"consercutive":"separate")<<endl; cout<<n[0]; for(int i=1;i<4;i++) { cout<<operator_char_def[oper[i-1]]<<n[i]; } cout<<endl; } void add_parenthesis(stringstream& ss) { ss.str("("+ss.str()+")"); ss.seekp(0,ios_base::end); } string get_consecutive_exp(int n[4],char oper[3]) { stringstream ss; ss<<n[0]<<operator_char_def[oper[0]]<<n[1]; if(oper[0]<2 && oper[1]>=2) add_parenthesis(ss); ss<<operator_char_def[oper[1]]<<n[2]; if(oper[1]<2 && oper[2]>=2) add_parenthesis(ss); ss<<operator_char_def[oper[2]]<<n[3]; return ss.str(); } string get_separate_exp(int n[4],char oper[3]) { stringstream ss; ss << '(' << n[0] << operator_char_def[oper[0]] << n[1] << ')'<< operator_char_def[oper[1]] << '(' << n[2] << operator_char_def[oper[2]] << n[3] << ')'; return ss.str(); } bool calc_24(int card[4]) { int n[4]; char oper[3]; for(int i1=0;i1<4;i1++) { n[0]=card[i1]; for(int i2=0;i2<4;i2++) { if(i2==i1) continue; n[1]=card[i2]; for(int i3=0;i3<4;i3++) { if(i3==i1||i3==i2) continue; n[2]=card[i3]; int i4 = 6-i1-i2-i3; n[3]=card[i4]; for(int j1=0;j1<4;j1++) { oper[0]=j1; for(int j2=0;j2<4;j2++) { oper[1]=j2; for(int j3=0;j3<4;j3++) { oper[2]=j3; if(calc_consecutive(n,oper)==24) { //tmp_output(1,n,oper); cout<<get_consecutive_exp(n,oper)<<endl; return true; } if(cale_separate(n,oper)==24) { //tmp_output(2,n,oper); cout<<get_separate_exp(n,oper)<<endl; return true; } } } } } } } return false; } int main() { int num[4]; cout<<"Press Ctrl+C to exit"<<endl; while(scanf("%d %d %d %d",&num[0],&num[1],&num[2],&num[3])!=EOF) { if(!calc_24(num)) { cout<<"No result"<<endl; } } return 0; }
对于打印多个符合条件的表达式的情况,只需要改几个地方
1、判断完是24后,打印完,不返回,所以calc_24()方法要修改下
2、如果要增加减法可以负数的情况,则把cale_separate(),calc_consecutive(),还有calc()方法中所有判断小于0的情况去掉即可
3、如果要增加除法可以为小数的情况,则需要把int改为float,并且去掉calc()方法中判断除法不为整数的条件即可