UESTC 1252 24点游戏 DFS

117 篇文章 2 订阅
15 篇文章 0 订阅

24点游戏

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

24 点就是给你一串数字,问你是否通过加减乘除括号构成 24 点。

沈爷觉得这个很好玩,就决定考考你,给你 4 个数,可以交换位置,可以用加减乘除和括号,是否能构成 24 点呢?

注意哦~这里的除法并不是整数除法,比如样例

Input

第一行 T ,表示有多少组测试数据, 1T50

接下来 T 行,每行 4 个正整数 a1 a2 a3 a4 ,表示每个数都是多少, 1ai13

Output

对于每一次询问,如果能够凑成 24 点,输出yes,否则输出no

Sample input and output

Sample Input Sample Output
2
3 3 8 8
1 1 1 1
yes
no

Hint

3   3   8   8

就可以构造出  8÷(38÷3)=24

Source

第七届ACM趣味程序设计竞赛第二场(正式赛) E


My Solution

是学长提醒了括号的处理才会的,因为括号只是改变优先级,先算后算的问题,如果第一次C4 2则每个两两都算然后作为一个数,
储存到一个变量a[ i ]中,另一个数在这个递归被去掉,然后把a[ n-1 ]移到这个数的空间储存,因为a[ n-1 ]那个位置下一次的递归
中不会访问,便于控制吧。第二次C3 2,第三次C2 2。因此,每个二元组分别+(1)、-(2)、*、/ (1 or 2 or 0) 。
且什么最多50组数据,所以最多36*18*6*50=194400 不会超时。
另外:
1、注意除 0 ,所以除的时候要讨论能不能除;
2、精度问题,这里要求的是实数运算,但没有真正的分数,8/(1/3),会是8/0.3333....所以有个精度问题,学长说误差eps=0.01以内就可以。
笔者觉得这里用float比较好,反正不会溢出,且比double快, Memory 也小一点吧。搜索中说double很容易出现浮点误差,而float一般没有;

#include <iostream>
#include <cstdio>
#include <cmath>
//#define LOCAL
float a[5];
//float感觉比double快一点
bool dfs(int n)
{
    if(n==1){
        if(fabs(a[0]-24)<1e-2) return true;
        else return false;
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            float x=a[i];        //写dfs的时候不能把这里x、y放到全局
            float y=a[j];
            a[j]=a[n-1];
            a[i]=x+y;if(dfs(n-1)) return true;
            a[i]=x-y;if(dfs(n-1)) return true;
            a[i]=y-x;if(dfs(n-1)) return true;
            a[i]=x*y;if(dfs(n-1)) return true;
            if(y) a[i]=x/y;if(dfs(n-1)) return true;
            if(x) a[i]=y/x;if(dfs(n-1)) return true;
            a[i]=x;
            a[j]=y;
        }
    }
    return false;
}

int main()
{
    #ifdef LOCAL
    freopen("a.txt","r",stdin);
    #endif // LOCAL
    int T;
    scanf("%d",&T);
    while(T--){
        for(int i=0;i<4;i++)
            scanf("%f",&a[i]);
        if(dfs(4)) printf("yes");
        else printf("no");
        if(T) printf("\n");
    }
    return 0;
}

谢谢


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值