题目描述:
问题描述:给出4个1-10的数字,通过加减乘除,得到数字为24就算胜利
输入:
4个1-10的数字。[数字允许重复,但每个数字仅允许使用一次,测试用例保证无异常数字。
输出:
true or false
本题含有多组样例输入。
输入描述:
输入4个int整数
输出描述:
返回能否得到24点,能输出true,不能输出false
示例:
输入:
7 2 1 10
输出:
true
解题思路:
本题是深度优先遍历dfs的经典题目:输入4个1-10的数字,用加减乘除使其结果为24。用dfs函数进行递归遍历求解,当计算到第四步时,step为3,此时判断是否为24,若有结果则令flag为true;声明num数组存放数字,声明visit数组存放当前数字是否可用。
假设输入数字为7654,则第一个遍历为7+6+5+4,再7+6+5-4。。。再7+6-5+4。。。。再7+6+4+5。。。以此类推。另外,dfs扔进去的和是前面的所有值计算完的结果再操作后面的值,换句话说,7+6+5*4,它扔进去的是(7+6+5)*4,虽然此时计算的结果和预想的不一样,别忘了还有排序,后面会有5*4+7+6的计算表达式,这样就确保了该计算的表达式依然会进行计算。
注意:因为sum初始为0,所以要考虑一下不同情况,不然会出现0*X=0。
测试代码:
#include <iostream> using namespace std; double num[4]; bool flag=false; bool visit[4]={0}; void dfs(int step,double sum) { if(flag) return; if(step==3) { if(sum==24.) { flag=true; return; } } else{ step++; for(int i=0;i<4;++i) { if(!visit[i]) { visit[i]=true; dfs(step,sum+num[i]); dfs(step,sum-num[i]); if(step!=0){ dfs(step,sum*num[i]); dfs(step,sum/num[i]); } visit[i]=false; if(flag) return; } } } } int main() { while(cin>>num[0]>>num[1]>>num[2]>>num[3]) { dfs(-1,0); if(flag) { cout<<"true"<<endl; } else{ cout<<"false"<<endl; } flag=false; num[4]={0}; visit[4]={0}; } return 0; }
后来测试我发现,1 9 1 2这个例子过不了,但是(9-1)*(2+1)=24,这是因为上面的算法考虑括号操作不周全导致的,牛客一名大佬“ultraji” 所提供的的算法思路更完善些,在此分享给大家。
其逻辑是:借用next_permutation函数排布4个数字的顺序,往里面塞入3个运算符,再用for循环处理各种可能的括号情况。其代码如下:
#include <iostream> #include <algorithm> #include <vector> #include <cmath> using namespace std; double op(double a, double b, int opera) { if(opera == 0) return a+b; else if(opera == 1) return a-b; else if(opera == 2) return a*b; else if(opera == 3) return a/b; return 0; } bool cal24(vector<double> a, vector<int> o) { // 考虑括号导致优先级变化 bool flag = false; if(o.empty()) { if( fabs(a[0]-24.0) < 0.01) flag = true; } else { for (int i = 0; i < o.size() && !flag; i++) { a[i] = op(a[i], a[i+1], o[i]); a.erase(a.begin()+i+1); o.erase(o.begin()+i); flag |= cal24(a, o); } } return flag; } int main() { double a[4]; int o[3]; while(cin >> a[0] >> a[1] >> a[2] >> a[3]) { bool flag = false; sort(a, a+4); do { for(int i = 0; i < 4 && !flag; i++) { o[0] = i; for(int j = 0; j < 4 && !flag; j++) { o[1] = j; for(int k = 0; k < 4 && !flag; k++) { o[2] = k; vector<double> va(a, a+4); vector<int> vo(o, o+3); if(cal24(va, vo)) flag = true; } } } } while (next_permutation(a, a+4) && !flag); if( flag ) cout << "true" << endl; else cout << "false" << endl; } return 0; }