hihoCoder搜索专题1---24点

题目链接:
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;  
}  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值