华为机试HJ67:24点游戏算法
Posted 翟天保Steven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了华为机试HJ67:24点游戏算法相关的知识,希望对你有一定的参考价值。
作者:Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
题目描述:
问题描述:给出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;
}
以上是关于华为机试HJ67:24点游戏算法的主要内容,如果未能解决你的问题,请参考以下文章