24点游戏
2017-08-05 22:44:37
一、判断是否有解
问题描述:
问题求解:
public boolean judgePoint24(int[] nums) { double[] nums_ = new double[4]; for (int i = 0; i < 4; i++) nums_[i] = nums[i] * 1.0; return helper(nums_, 4); } private boolean helper(double[] nums, int n) { if (n == 1) return Math.abs(nums[0] - 24) < 0.001; double[] nums_ = Arrays.copyOf(nums, n); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { double[] res = calc(nums[i], nums[j]); for (double k : res) { nums_[i] = k; nums_[j] = nums[n - 1]; if (helper(nums_, n - 1)) return true; nums_[j] = nums[j]; nums_[i] = nums[i]; } } } return false; } private double[] calc(double i, double j) { return new double[]{i + j, i - j, j - i, j * i, i / j, j / i}; }
二、打印所有解
24点的计算问题我从小就在玩,而且还玩的不错。不过学习编程之后呢,一直没有系统的解决过这个问题。之前做华为的编程测试题的时候有一条算24的题,是采用的暴力枚举的方式进行的。这次采用了递归的方法进行计算。算法思想如下:
- n个数算24,必有两个数要先算。这两个数算的结果,和剩余n-2个数,就构成了n-1个数求24的问题
- 枚举先算的两个数,以及这两个数的运算方式。
- 边界条件:一个数算24
- 注意:浮点数比较是否相等,不能用 ==
double a[5]; #define EPS 1e-6 vector<double> vec; string str; bool isZero(double x) { return fabs(x) <= EPS; } string d2s(double in) { stringstream s; string rst; s<<in; s>>rst; return rst; } bool count24(double a[],int n) {// 用数组a 里的 n 个数,计算24 if( n == 1 ) { if(isZero( a[0] - 24) ) { for(int i=0;i<vec.size();++i) cout<<vec[i]<<" "; cout<<endl; cout<<str<<endl; return true; } else return false; } double b[5]; for(int i = 0;i < n-1; ++i) for(int j = i+1;j < n; ++j) { // 枚举两个数的组合 int m = 0; // 还剩下m 个数, m = n - 2 for(int k = 0; k < n; ++k) if( k != i && k!= j) b[m++] = a[k];// 把其余数放入b vec.push_back(a[i]); vec.push_back(a[j]); b[m] = a[i]+a[j]; str.append("+"); if(count24(b,m+1)) return true; str.pop_back(); str.append("-"); b[m] = a[i]-a[j]; if(count24(b,m+1)) return true; b[m] = a[j]-a[i]; if(count24(b,m+1)) return true; str.pop_back(); b[m] = a[i]*a[j]; str.append("*"); if(count24(b,m+1)) return true; str.pop_back(); if( !isZero(a[j])) { b[m] = a[i]/a[j]; str.append("/"); if(count24(b,m+1)) return true; str.pop_back(); } if( !isZero(a[i])) { str.append("/"); b[m] = a[j]/a[i]; if(count24(b,m+1)) return true; str.pop_back(); } vec.pop_back(); vec.pop_back(); } return false; }
string print(int i,int j,double ans=24)
{
if(i<0||j<0) return d2s(vec[1]);
if(str[j]=='+') return d2s(vec[i])+"+("+print(i-2,j-1,vec[i+1])+")";
if(str[j]=='*') return d2s(vec[i])+"*("+print(i-2,j-1,vec[i+1])+")";
if(str[j]=='-')
{
if(abs((vec[i]-vec[i+1]-ans))<=EPS) return d2s(vec[i])+"-("+print(i-2,j-1,vec[i+1])+")";
else return "("+print(i-2,j-1,vec[i+1])+")-"+d2s(vec[i]);
}
if(str[j]=='/')
{
if(abs((vec[i]/vec[i+1]-ans))<=EPS) return d2s(vec[i])+"/("+print(i-2,j-1,vec[i+1])+")";
else return "("+print(i-2,j-1,vec[i+1])+")/"+d2s(vec[i]);
}
} int main() { for(int i = 0;i < 4; ++i) cin >> a[i]; if( count24(a,4)) { cout << "YES" << endl; cout<<print(4,2,24)<<endl; } else cout << "NO" << endl; return 0; }
如果需要输出所有的解:
double a[5]; #define EPS 1e-6 vector<double> vec; string str; bool isZero(double x) { return fabs(x) <= EPS; } string d2s(double in) { stringstream s; string rst; s<<in; s>>rst; return rst; } string print(int i,int j,double ans=24) { if(i<0||j<0) return d2s(vec[1]); if(str[j]=='+') return d2s(vec[i])+"+("+print(i-2,j-1,vec[i+1])+")"; if(str[j]=='*') return d2s(vec[i])+"*("+print(i-2,j-1,vec[i+1])+")"; if(str[j]=='-') { if(abs((vec[i]-vec[i+1]-ans))<=EPS) return d2s(vec[i])+"-("+print(i-2,j-1,vec[i+1])+")"; else return "("+print(i-2,j-1,vec[i+1])+")-"+d2s(vec[i]); } if(str[j]=='/') { if(abs((vec[i]/vec[i+1]-ans))<=EPS) return d2s(vec[i])+"/("+print(i-2,j-1,vec[i+1])+")"; else return "("+print(i-2,j-1,vec[i+1])+")/"+d2s(vec[i]); } } void count24(double a[],int n) {// 用数组a 里的 n 个数,计算24 if( n == 1 ) { if(isZero( a[0] - 24) ) { for(int i=0;i<vec.size();++i) cout<<vec[i]<<" "; cout<<endl; cout<<print(4,2,24)<<endl; } } double b[5]; for(int i = 0;i < n-1; ++i) for(int j = i+1;j < n; ++j) { // 枚举两个数的组合 int m = 0; // 还剩下m 个数, m = n - 2 for(int k = 0; k < n; ++k) if( k != i && k!= j) b[m++] = a[k];// 把其余数放入b vec.push_back(a[i]); vec.push_back(a[j]); b[m] = a[i]+a[j]; str.append("+"); count24(b,m+1); str.pop_back(); str.append("-"); b[m] = a[i]-a[j]; count24(b,m+1); str.pop_back(); str.append("-"); b[m] = a[j]-a[i]; count24(b,m+1); str.pop_back(); str.append("*"); b[m] = a[i]*a[j]; count24(b,m+1); str.pop_back(); if( !isZero(a[j])) { b[m] = a[i]/a[j]; str.append("/"); count24(b,m+1); str.pop_back(); } if( !isZero(a[i])) { str.append("/"); b[m] = a[j]/a[i]; count24(b,m+1); str.pop_back(); } vec.pop_back(); vec.pop_back(); } } int main() { for(int i = 0;i < 4; ++i) cin >> a[i]; count24(a,4); return 0; }