您的位置:首页 > 其它

hihoCoder搜索专题1---24点

2016-06-12 22:17 197 查看
题目链接:

http://hihocoder.com/problemset/problem/1304

24点规则,抽取扑克中的四张牌,每张牌使用一次的情况下进行三次加减乘除运算,考虑是否能得到24这个数。

首先是解题思路,在题目里也有给出,这里我自己做了归纳;

1.定义运算符 ⊙:

用于表示6种运算,在原本的加、减、乘、除的基础上加上被减、和被除;

被减的意思是交换两个数在减和除运算符的前后位置,比如a-b还可以有b-a这种情况。

2.两种模式:

(((a⊙b)⊙c)⊙d) 和

((a⊙b)⊙(c⊙d));

3.复杂度计算:

4个数字全排列表示所有数字位置情况:4!=24

3个运算符⊙,每个有6种情况:6^3 = 216

两种模式 : x2

所以:24 * 216 * 2= 10368

又因为 a+b与a*b分别等价于b+a与b * a;

所以总情况肯定小于10368.

下面是代码实现思路:

1.先搜索全排列,再搜索运算符。

2.搜索数字时注意标记每个数字使用一次,而每个运算可以使用多次。

3.两种模式的计算方法(具体见代码)

我自己照着上述思路写了100多一点行,而在网上看到有大牛简化写只用了50左右,佩服,也贴在下方。

这是我自己写的:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int num[4];
int used[4] = { 0 };
int nowNumber[4] = { 0 };
char ops[6] = { '+','-','*','/','$','&' };
char nowOps[3];
int ant = 0;
bool makeOps(int depth2);
double calc(double sum, char c, double d)
{
if (c == '+')
return sum + d;
if (c == '-')
return sum - d;
if (c == '*')
return sum*d;
if (c == '/')
return sum / d;
if (c == '$')
return d - sum;
if (c == '&')
return d / sum;
}
double calcType1(int nowNumber[], char nowOps[])
{
double sum = nowNumber[0];
for (int l1 = 0; l1<3; l1++)
{
sum = calc(sum, nowOps[l1], nowNumber[l1 + 1]);
}
return sum;
}
double calcType2(int nowNumber[], char nowOps[])
{
double sum1 = nowNumber[0];
double sum2 = nowNumber[2];
double sum;
sum1 = calc(sum1, nowOps[0], nowNumber[1]);
sum2 = calc(sum2, nowOps[2], nowNumber[3]);
sum = calc(sum1, nowOps[1], sum2);
return sum;
}
bool makeNumber(int depth1)
{
if (depth1 >= 4)
{
if (makeOps(0))
return true;
else return false;
}
for (int i = 0; i<4; i++)
{
if (used[i] == 0)
{
nowNumber[depth1] = num[i];
used[i] = 1;
if (makeNumber(depth1 + 1))
{
return true;
}
used[i] = 0;
}
}
return false;
}
bool makeOps(int depth2)
{
if (depth2 >= 3)
{
if (calcType1(nowNumber, nowOps) == 24)
{
//cout<<"("<<"("<<"("<<nowNumber[0]<<nowOps[0]<<nowNumber[1]<<")"<<nowOps[1]<<nowNumber[2]<<")"<<nowOps[2]<<nowNumber[3]<<")"<<endl;
return true;
}
else if (calcType2(nowNumber, nowOps) == 24)
{
//cout<<"("<<"("<<nowNumber[0]<<nowOps[0]<<nowNumber[1]<<")"<<nowOps[1]<<"("<<nowNumber[2]<<nowOps[2]<<nowNumber[3]<<")"<<")"<<endl;
return true;
}
return false;
}
for (int j = 0; j<6; j++)
{
nowOps[depth2] = ops[j];
if (makeOps(depth2 + 1))
{
return true;
}
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
memset(used, 0, sizeof(used));
memset(nowNumber, 0, sizeof(nowNumber));
memset(nowOps, 0, sizeof(nowOps));
for (int w = 0; w<4; w++)
{
scanf("%d", &num[w]);
}
if(makeNumber(0))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}


这是大牛的简化:http://blog.csdn.net/qq_28954601/article/details/51425433

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
double a[4];
bool flag;
double so(double a,double b,int k)
{
double s=0.0;
switch(k)
{
case 0:s=a+b;break;
case 1:s=a-b;break;
case 2:s=a*b;break;
case 3:if(b!=0)s=a/b;break;
case 4:s=b-a;break;
case 5:if(a!=0)s=b/a;break;
}
return s;
}
bool pan(int i,int j,int k)
{
if(so(so(so(a[0],a[1],i),a[2],j),a[3],k)==24)return true;
if(so(so(a[0],a[1],i),so(a[2],a[3],k),j)==24)return true;
return false;
}
void solve()
{
for(int i=0; i<6; i++)
for(int j=0; j<6; j++)
for(int k=0; k<6; k++)
if(pan(i,j,k))
{
flag=true;
return;
}
}
int main()
{
int N;
cin>>N;
while(N--)
{
flag=false;
for(int i=0; i<4; i++)
cin>>a[i];
sort(a,a+4);
do
{
solve();
if(flag)break;
}
while(next_permutation(a,a+4));
if(flag)printf("Yes\n");
else printf("No\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: