• 经典游戏--24点--c++代码实现和总体思路(简单暴力向)


    24点

      24点是一个非常经典的游戏,从扑克牌里抽4张牌,其中J=11,Q=12,K=13,然后经过+,-,*,/,(),的计算后,使得计算得值为24,例如抽到1,2,2,5四张牌,那么

      (1+5)*(2+2)=24;

      这就是可以凑成24点的一种情况,作为一个经典题目,在leetcode上也有对应的题目进行练习

      PS 看见知乎大佬有一种必24点的算法,但是要用到阶乘和次方 式子为(a0+b0+c0+d0)! =24

    一、总体思路

      1.因为是简单暴力向的,所以我们的做法就是直接穷举出所有可能的情况,首先是考虑四个数a,b,c,d的排列情况

        如b,a,c,d等等,通过排列组合可以得到 4*3*2*1 = 24 种情况

      2.然后考虑a,b,c,d中的三个运算符的情况设一个自定义的运算符为$,$可以是+,-,*,/中的任意一个

        则有 a$b$c$d 这个式子,同样,运算符的可能性有 3*4 = 12 种

      3.最后考虑()的情况,我们规定,每次一对()只框住两个数,比如a+b+c+d =(((a+b)+c)+d) = ((r1+c)+d)=(r2+d)=r3(其中r1=a+b,r2=r1+c,r3=r2+d)

        ()的情况其实就是运算优先级的问题,无论运算符是什么,都一定是先运算括号里的内容

        所以我们可以穷举出情况

        第一种r1=a$b,r2=r1$c,r3=r2$d;

        第二种r1=b$c,r2=a$r1,r3=r2$d;

        第三种r1=b$c,r2=r1$d,r3=a$r2;

        第四种r1=c$d,r2=b$r1,r3=a$r2;

        第五种r1=a$b,r2=c$d,r3=r1$r2;

      仔细观察不难发现,我们控制了运算符和数字的绝对顺序从左到右的顺序严格是a$b$c$d,不论任何情况都不会改变abcd的顺序,是因为我们在上面已经排出来了所有的24种情况,所以我们这就可以严格控制abcd的顺序了

    二、代码实现

      1 #include <iostream>
      2 #include <string>
      3 using namespace std;
      4 int mark_int[4] = { 1,2,3,4 };
      5 string mark_char = "+-*/";
      6 double cal(double a, int m, double b)
      7 {
      8     switch (m)
      9     {
     10     case 1:    return a + b;
     11     case 2:    return a - b;
     12     case 3:    return a * b;
     13     case 4:    return a / b;
     14     }
     15 }
     16 
     17 bool cal1(double a, double b, double c, double d, int m1, int m2, int m3)
     18 {
     19     double r1;
     20     double r2;
     21     double r3;
     22     r1 = cal(a, m1, b);
     23     r2 = cal(r1, m2, c);
     24     r3 = cal(r2, m3, d);
     25     if (r3 == 24)
     26     {
     27         cout << "(((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << ")" << endl;
     28         return 1;
     29     }
     30     return 0;
     31 }
     32 
     33 bool cal2(int a, int b, int c, int d, int m1, int m2, int m3)
     34 {
     35     double r1;
     36     double r2;
     37     double r3;
     38     r1 = cal(b, m1, c);
     39     r2 = cal(a, m2, r1);
     40     r3 = cal(r2, m3, d);
     41     if (r3 == 24)
     42     {
     43         cout << "((" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << c << "))" << mark_char[m3 - 1] << d << ")" << endl;
     44         return 1;
     45     }
     46     return 0;
     47 }
     48 
     49 bool cal3(int a, int b, int c, int d, int m1, int m2, int m3)
     50 {
     51     double r1;
     52     double r2;
     53     double r3;
     54     r1 = cal(b, m1, c);
     55     r2 = cal(r1, m2, d);
     56     r3 = cal(a, m3, r2);
     57     if (r3 == 24)
     58     {
     59         cout << "(" << a << mark_char[m1 - 1] << "((" << b << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << "))" << endl;
     60         return 1;
     61     }
     62     return 0;
     63 }
     64 
     65 bool cal4(int a, int b, int c, int d, int m1, int m2, int m3)
     66 {
     67     double r1;
     68     double r2;
     69     double r3;
     70     r1 = cal(c, m1, d);
     71     r2 = cal(b, m2, r1);
     72     r3 = cal(a, m3, r2);
     73     if (r3 == 24)
     74     {
     75         cout << "(" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << ")))" << endl;
     76         return 1;
     77     }
     78     return 0;
     79 }
     80 
     81 bool cal5(int a, int b, int c, int d, int m1, int m2, int m3)
     82 {
     83     double r1;
     84     double r2;
     85     double r3;
     86     r1 = cal(a, m1, b);
     87     r2 = cal(c, m3, d);
     88     r3 = cal(r1, m2, r2);
     89     if (r3 == 24)
     90     {
     91         cout << "((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << "))" << endl;
     92         return 1;
     93     }
     94     return 0;
     95 }
     96 
     97 
     98 bool all_cal(int a, int b, int c, int d)
     99 {
    100     for (int i = 1; i <= 4; i++)
    101         for (int j = 1; j <= 4; j++)
    102             for (int k = 1; k <= 4; k++)
    103             {
    104                 if (cal1(a, b, c, d, i, j, k) == true || cal2(a, b, c, d, i, j, k) == true || cal3(a, b, c, d, i, j, k) == true || cal4(a, b, c, d, i, j, k) == true || cal5(a, b, c, d, i, j, k) == true)
    105                     return 1;
    106             }
    107     return 0;
    108 }
    109 
    110 
    111 bool judge(int a, int b, int c, int d)
    112 {
    113     int all[24][4] = {
    114         {a,b,c,d},{a,b,d,c},{a,c,b,d},{a,c,d,b},{a,d,b,c},{a,d,c,b},
    115         {b,a,c,d},{b,a,d,c},{b,c,a,d},{b,c,d,a},{b,d,a,c},{b,d,c,a},
    116         {c,a,b,d},{c,a,d,b},{c,b,a,d},{c,b,d,a},{c,d,a,b},{c,d,b,a},
    117         {d,a,b,d},{d,a,d,b},{d,b,a,c},{d,b,c,a},{d,c,a,b},{d,c,b,a},
    118     };
    119     for (int i = 0; i < 24; i++)
    120     {
    121         if (all_cal(all[i][0], all[i][1], all[i][2], all[i][3]))
    122             return 1;
    123     }
    124     return 0;
    125 }
    126 
    127 int main()
    128 {
    129     int a, b, c, d;
    130     cin >> a >> b >> c >> d;
    131     if (!judge(a, b, c, d))
    132         cout << "凑不成24点" << endl;
    133 
    134 }

    三、代码解释

    先做一个计算两个数的函数,用数组int mark_int[4] = {1,2,3,4}的四个数表示+ - * /,string mark_char是用来最后显示的

     1 int mark_int[4] = { 1,2,3,4 };
     2 string mark_char = "+-*/";
     3 double cal(double a, int m, double b)
     4 {
     5     switch (m)//用switch来进行运算符的选择
     6     {
     7     case 1:    return a + b;
     8     case 2:    return a - b;
     9     case 3:    return a * b;
    10     case 4:    return a / b;
    11     }
    12 }

    我们在实现五种括号的函数,并且我们规定运算一定是 a m1 b m2 c m3 d(m1,m2,m3是三个运算符的代号),意思就是abcd的从左到右顺序不乱,m1m2m3从左到右的顺序也不会乱,比较粗暴的理解就是ab之间一定是m1,bc之间一定是m2,cd之间一定其实m3,然后如果成功返回运算的过程和true,否则返回false

     1 bool cal1(double a, double b, double c, double d, int m1, int m2, int m3)
     2 {
     3     double r1;
     4     double r2;
     5     double r3;
     6     r1 = cal(a, m1, b);
     7     r2 = cal(r1, m2, c);
     8     r3 = cal(r2, m3, d);
     9     if (r3 == 24)
    10     {
    11         cout << "(((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << ")" << endl;
    12         return 1;
    13     }
    14     return 0;
    15 }//第一种r1=a$b,r2=r1$c,r3=r2$d;
    16 
    17 bool cal2(int a, int b, int c, int d, int m1, int m2, int m3)
    18 {
    19     double r1;
    20     double r2;
    21     double r3;
    22     r1 = cal(b, m1, c);
    23     r2 = cal(a, m2, r1);
    24     r3 = cal(r2, m3, d);
    25     if (r3 == 24)
    26     {
    27         cout << "((" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << c << "))" << mark_char[m3 - 1] << d << ")" << endl;
    28         return 1;
    29     }
    30     return 0;
    31 }//第二种r1=b$c,r2=a$r1,r3=r2$d;
    32 
    33 bool cal3(int a, int b, int c, int d, int m1, int m2, int m3)
    34 {
    35     double r1;
    36     double r2;
    37     double r3;
    38     r1 = cal(b, m1, c);
    39     r2 = cal(r1, m2, d);
    40     r3 = cal(a, m3, r2);
    41     if (r3 == 24)
    42     {
    43         cout << "(" << a << mark_char[m1 - 1] << "((" << b << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << "))" << endl;
    44         return 1;
    45     }
    46     return 0;
    47 }//第三种r1=b$c,r2=r1$d,r3=a$r2;
    48 
    49 bool cal4(int a, int b, int c, int d, int m1, int m2, int m3)
    50 {
    51     double r1;
    52     double r2;
    53     double r3;
    54     r1 = cal(c, m1, d);
    55     r2 = cal(b, m2, r1);
    56     r3 = cal(a, m3, r2);
    57     if (r3 == 24)
    58     {
    59         cout << "(" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << ")))" << endl;
    60         return 1;
    61     }
    62     return 0;
    63 }//第四种r1=c$d,r2=b$r1,r3=a$r2;
    64 
    65 bool cal5(int a, int b, int c, int d, int m1, int m2, int m3)
    66 {
    67     double r1;
    68     double r2;
    69     double r3;
    70     r1 = cal(a, m1, b);
    71     r2 = cal(c, m3, d);
    72     r3 = cal(r1, m2, r2);
    73     if (r3 == 24)
    74     {
    75         cout << "((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << "))" << endl;
    76         return 1;
    77     }
    78     return 0;
    79 }//第五种r1=a$b,r2=c$d,r3=r1$r2;

    接下来是12种的符号的排列情况,如果有一种括号情况满足,我们就返回true,否则返回false

     1 bool all_cal(int a, int b, int c, int d)
     2 {
     3     for (int i = 1; i <= 4; i++)
     4         for (int j = 1; j <= 4; j++)
     5             for (int k = 1; k <= 4; k++)
     6             {
     7                 if (cal1(a, b, c, d, i, j, k) == true || cal2(a, b, c, d, i, j, k) == true || cal3(a, b, c, d, i, j, k) == true || cal4(a, b, c, d, i, j, k) == true || cal5(a, b, c, d, i, j, k) == true)
     8                     return 1;
     9             }
    10     return 0;
    11 }

    最后是在总判断函数中写入24种的abcd排列情况

     1 bool judge(int a, int b, int c, int d)
     2 {
     3     int all[24][4] = {
     4         {a,b,c,d},{a,b,d,c},{a,c,b,d},{a,c,d,b},{a,d,b,c},{a,d,c,b},
     5         {b,a,c,d},{b,a,d,c},{b,c,a,d},{b,c,d,a},{b,d,a,c},{b,d,c,a},
     6         {c,a,b,d},{c,a,d,b},{c,b,a,d},{c,b,d,a},{c,d,a,b},{c,d,b,a},
     7         {d,a,b,d},{d,a,d,b},{d,b,a,c},{d,b,c,a},{d,c,a,b},{d,c,b,a},
     8     };
     9     for (int i = 0; i < 24; i++)
    10     {
    11         if (all_cal(all[i][0], all[i][1], all[i][2], all[i][3]))
    12             return 1;
    13     }
    14     return 0;
    15 }

    主函数调用judge就完成整个算法了✿✿ヽ(°▽°)ノ✿

    1 int main()
    2 {
    3     int a, b, c, d;
    4     cin >> a >> b >> c >> d;
    5     if (!judge(a, b, c, d))
    6         cout << "凑不成24点" << endl;
    7 
    8 }

    失败的话会显示“凑不成24点”

    其实这个算法的话我写的可以说基本没有优化,就是枚举所有情况实现的,csdn上有大佬是有更好的思路的,这篇文章也是看了csdn的大佬的代码然后自己修修补补写出来的(我原来看的那篇有bug,大佬自己没发现好像。。。)

    就酱

    睡觉!

      

  • 相关阅读:
    QT中PRO文件写法的详细介绍,很有用,很重要!
    What is the difference between authorized_key and known_host file for SSH
    SHELL DATE 命令详解
    Sample program to use PC/SC API.
    如何让用户关闭客户端IE时,触发Session_End事件
    Sql Create Function简单例子
    Css2.0实现圆角边框
    运算符重载的一个例子
    HTML获取URL传递的参数
    C#中自定义属性的例子
  • 原文地址:https://www.cnblogs.com/luoyoucode/p/13551552.html
Copyright © 2020-2023  润新知