来自电子科技大学的挑战

寒假的时候我和我的高中同学在交流的时候给我了一道题,听说比较难,初次尝试并且和我的高中同学一起讨论过后的结果
                            下面是这道题的原题和自己认为的解题步骤

计算 24 点是一种扑克牌益智游戏,随机抽出 4 张扑克牌,通过加 (+) ,减 (-) ,乘 ( * ), 除 (/) 四种运算法则计算得到整数 24 ,本问题中,扑克牌通过如下字符表示:

A 2 3 4 5 6 7 8 9 10 J Q K

详细说明:

1. 运算只考虑加减乘除运算,没有阶乘等特殊运算符号, 友情提醒,整数除法要当心 ;

2. 牌面 2~10 对应的权值为 2~10, J 、 Q 、 K 、 A 权值分别为为 11 、 12 、 13 、 1 ;

3. 输入 4 张牌为字符串形式,例如:A346

4. 输出的算式格式为 4 张牌通过 +-*/ 四个运算符相连, 中间无空格 , 4 张牌出现顺序任意,只要结果正确;

5. 输出算式的运算顺序从左至右,不包含括号 ,如 1*2*3*4 的结果为 24

6. 如果存在多种算式都能计算得出 24 ,只需输出一种即可,如果无法得出 24 ,则输出“ NONE ”表示无解。#include <stdio.h>

#include <ctype.h>

#include <math.h>

//A 2 3 4 5 6 7 8 9 10 J Q K

#define eps 1e-4

int read() {

    char ch1, ch2;

    ch1 = getchar();

    ch2 = getchar();

    if(isalnum(ch2)) {

        getchar();

        return 10;

    }

    else {

        switch(ch1) {

            case 'A' :  return 1;

            case 'J' :  return 11;

            case 'Q' :  return 12;

            case 'K' :  return 13;

            default:    return ch1-'0';  //其他情况

        }

    }

}

 

char tochar(int op) {

    if(op == 1) return '+';

    else if(op == 2) return '-';

    else if(op == 3) return '*';

    else return '/';

}

 

double cal(double a, int op, double b) {

    if(op == 1) return a+b;

    else if(op == 2) return a-b;

    else if(op == 3) return a*b;

    else {

//printf("%lf / %lf = %lf\n", a, b, a/b);

return a/b;

}

}

 

int main()

{

    int card[4], flag = 0;

    int ord[24] = {1234, 1243, 1324, 1342, 1423, 1432,

                   2134, 2143, 2314, 2341, 2413, 2431,

                   3124, 3142, 3214, 3241, 3412, 3421,

                   4123, 4132, 4213, 4231, 4312, 4321};

 

    for(int i = 0; i < 4; i++) {

        card[i] = read();

//        printf("%d ", card[i]);

    }

    

    for(int i = 0; i < 24; i++) {

    

        int ocard[4], opt = ord[i];

        ocard[0] = (double)card[opt/1000-1];     ocard[1] = (double)card[opt/100%10-1];

        ocard[2] = (double)card[opt/10%10-1];    ocard[3] = (double)card[opt%10-1];

        int op1, op2, op3;

        double ans;

        for(op1 = 1; op1 <= 4; op1++) {

            for(op2 = 1; op2 <= 4; op2++) {

                for(op3 = 1; op3 <= 4; op3++) {

                

                    if(op1 > 2) {

                        ans = cal(ocard[0], op1, ocard[1]);

                        if(op2 > 2 || (op2 <= 2 && op3 <= 2))

                            ans = cal(cal(ans, op2, ocard[2]), op3, ocard[3]);

                        else

                            ans = cal(ans, op2, cal(ocard[2], op3, ocard[3]));

                    }

                    else {

                        if(op2 > 2 && op3 > 2) {

                            ans = cal(cal(ocard[1], op2, ocard[2]), op3, ocard[3]);

                            ans = cal(ocard[0], op1, ans);

                        }

                        else if(op2 > 2) {

                            ans = cal(ocard[1], op2, ocard[2]);

                            ans = cal(cal(ocard[0], op1, ans), op3, ocard[3]);

                        }

                        else if(op3 > 2) {

                            ans = cal(ocard[2], op3, ocard[3]);

                            ans = cal(cal(ocard[0], op1, ocard[1]), op2, ans);

                        }

                        else {

                            ans = cal(ocard[0], op1, ocard[1]);

                            ans = cal(cal(ans, op2, ocard[2]), op3, ocard[3]);

                        }

                    }

 

                    if(fabs(ans-24) < eps) {

                        flag = 1;

                        printf("%d %c %d %c %d %c %d == 24\n", ocard[0], tochar(op1), ocard[1], tochar(op2), ocard[2], tochar(op3), ocard[3]);

                        break;

                    }

                }

                if(flag) break;

            }

            if(flag) break;

        }

        if(flag) break;

    }

    if(flag == 0) printf("NONE\n");

    return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值