hihoCoder--1304 搜索一·24点

描述

周末,小Hi和小Ho都在家待着。

在收拾完房间时,小Ho偶然发现了一副扑克,于是两人考虑用这副扑克来打发时间。

小Ho:玩点什么好呢?

小Hi:两个人啊,不如来玩24点怎么样,不靠运气就靠实力的游戏。

小Ho:好啊,好啊。

<经过若干局游戏之后>

小Ho:小Hi,你说如果要写个程序来玩24点会不会很复杂啊?

小Hi:让我想想。

<过了几分钟>

小Hi:我知道了!其实很简单嘛。

提示:24点

输入

第1行:1个正整数, t,表示数据组数,2≤t≤100。

第2..t+1行:4个正整数, a,b,c,d,1≤a,b,c,d≤10。

输出

第1..t行:每行一个字符串,第i行表示第i组能否计算出24点。若能够输出”Yes”,否则输出”No”。

样例输入

2
5 5 5 1
9 9 9 9

样例输出

Yes
No

题解

枚举a, b, c, d每一种排列,再枚举三种运算,根据提示,如果增加反-反/两种操作(很妙的思路),所有的计算过程只有两种:
1. (((a @ b) @ c) @ d)
2. (a @ b) @ (c @ d)

#include <bits/stdc++.h>
using namespace std;

double nums[4];  // a, b, c, d
double number[4];
bool used[4];
int opType[6];  // +, - , * , /, 反-, 反/
int ops[3];
int t;

double f(double a, double b, int op){
    double ret = 0;
    switch (op){
        case 0:
            ret = a + b; break;
        case 1:
            ret = a - b; break;
        case 2:
            ret = a * b; break;
        case 3:
            if(b != 0)
                ret = a / b; break;
        case 4:
            ret = b - a; break;
        case 5:
            if(a != 0)
                ret = b / a; break;
        }
    return ret;
}

int calc(){
    // (((a @ b) @ c) @ d)
    if(f(f(f(nums[0], nums[1], ops[0]), nums[2], ops[1]), nums[3], ops[2]) == 24) return true;
    // (a @ b) @ (c @ d)
    if(f(f(nums[0], nums[1], ops[0]), f(nums[2], nums[3], ops[2]), ops[1]) == 24) return true;

    return false;
}

int calc(int i, int j, int k){
    // (((a @ b) @ c) @ d)
    if(f(f(f(nums[0], nums[1], i), nums[2], j), nums[3], k) == 24) return true;
    // (a @ b) @ (c @ d)
    if(f(f(nums[0], nums[1], i), f(nums[2], nums[3], k), j) == 24) return true;

    return false;
}

bool dfs(int cur){
    if(cur >= 3){
        if(calc()) return true;
        else return false;
    }
    for(int i = 0; i < 6; ++i){
        ops[cur] = i;
        if(dfs(cur + 1)) return true;
    }
    return false;
}

bool judge(){
    for(int i = 0; i < 6; ++i){
        for(int j = 0; j < 6; ++j){
            for(int k = 0; k < 6; ++k){
                if(calc(i, j, k)) return true;
            }
        }
    }
    return false;
}

bool makeNumber(int cur){
    if(cur >= 4) return dfs(0);

    for(int i = 0; i < 4; ++i){
        if(!used[i]){
            nums[cur] = number[i];
            used[i] = true;
            if(makeNumber(cur + 1)) return true;
            used[i] = false;
        }
    }
    return false;
}

int main(){
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif // ONLINE_JUDGE

    cin >> t;
    while(t--){
        for(int i = 0; i < 4; ++i) cin >> number[i];
        memset(used, 0, sizeof(used));
        if(makeNumber(0)) cout << "Yes" << endl;
        else cout << "No" << endl;
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值