主要使用了dfs的算法,比较麻烦的是如何去重,去重第一步可以用set来保存式子,然后再去多余的括号,然后在用另一个set去重。但是做到真正的去重还是比较麻烦,如果有好的建议的博友,可以私信。比如1*2*3*4与2*3*1*4其实是重复的2*(1+2)*4与2*4*(1+2)是重复的。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<set> #include<iterator> using namespace std; int cmp(int a,int b){return a<=b;} void moveBrak(char* str); int m[4]; //使用set主要是为了去重 set<string> ss; void dfs(int sum,int cur,int i,string strSum,string strCur) { if(i==3) { char strTemp[100]; if(sum+cur==24){ sprintf(strTemp,"%s + %s = 24",strSum.c_str(),strCur.c_str()); ss.insert(strTemp); } else if(sum - cur==24){ sprintf(strTemp,"%s - %s = 24",strSum.c_str(),strCur.c_str()); ss.insert(strTemp); } else if(sum * cur==24){ sprintf(strTemp,"%s * %s = 24",strSum.c_str(),strCur.c_str()); ss.insert(strTemp); } else if(cur && sum%cur==0 && sum / cur == 24){ sprintf(strTemp,"%s / %s = 24",strSum.c_str(),strCur.c_str()); ss.insert(strTemp); } return; } char strTemp[100]; sprintf(strTemp,"%d",m[i+1]); dfs(sum,cur+m[i+1],i+1,strSum,"( "+strCur+" + "+strTemp+" )"); dfs(sum,cur-m[i+1],i+1,strSum,"( "+strCur+" - "+strTemp+" )"); dfs(sum,cur*m[i+1],i+1,strSum ,strCur+" * "+strTemp); if(m[i+1] && cur%m[i+1]==0) dfs(sum,cur/m[i+1],i+1,strSum,strCur+" / "+strTemp); dfs(sum+cur,m[i+1],i+1,"( "+strSum+" + "+strCur+" )",strTemp); dfs(sum-cur,m[i+1],i+1,"( "+strSum+" - "+strCur+" )",strTemp); dfs(sum*cur,m[i+1],i+1, strSum+" * "+strCur,strTemp); if(cur && sum%cur==0) dfs(sum/cur,m[i+1],i+1,strSum+" / "+strCur,strTemp); } int main() { while(~scanf("%d%d%d%d",&m[0],&m[1],&m[2],&m[3])) { ss.clear(); sort(m,m+4,cmp); do { char strTemp[100]; sprintf(strTemp,"%d",m[0]); string strSum = strTemp,strCur; sprintf(strTemp,"%d",m[1]); strCur = strTemp; dfs(m[0],m[1],1,strSum,strCur); }while(next_permutation(m,m+4)); set<string>::iterator it = ss.begin(); set<string> res; //去无效括号 for(;it!=ss.end();it++) { char strTemp[100]; strcpy(strTemp,it->c_str()); moveBrak(strTemp); res.insert(strTemp); } int cnt = 0; it = res.begin(); for(;it!=res.end();it++,++cnt) printf("%s\n",it->c_str()); if(cnt) printf("总共有%d个算式\n",cnt); else printf("没有符合条件的算式\n"); } return 0; } void moveBrak(char* str) { if(true) return; int len = strlen(str); //dev表示去掉的括号,left,right表示保留的括号 char dev = '#',left = '$',right = '&'; for(int i=0;i<len;++i) { if(str[i]==')') { int j = i-1; for(;j>=0;--j) if(str[j]=='(') break; //是否去掉括号 bool bDev = false; if(i<len-2&&(str[i+2]=='+'||str[i+2]=='-')) bDev = true; if(j>=2&&(str[j-2]=='+')) bDev = true; else if(j>=2&&(str[j-2]=='-'||str[j-2]=='*'||str[j-2]=='/')) bDev = false; if(bDev) str[i] = str[j] = dev; else str[i] = right,str[j] = left; } } char strTemp[100]; int k = 0; for(int i=0;i<len;++i) { if(str[i]==dev) { ++i; continue; } if(str[i]==left) strTemp[k++] = '('; else if(str[i]==right) strTemp[k++] = ')'; else strTemp[k++] = str[i]; } strTemp[k++] = '\0'; memcpy(str,strTemp,k); }