• 【算法29】速算24


    问题描述

    题目来源:PAT ds 2-08

    给定四个数字a, b, c, d,取值范围为[1, 13];添加合适的运算符 + , - , * , /, 和括号(, )使得表达式等于24,给出一种可能的表达式方案;如果不可能则返回-1。

    例如:输入2, 3, 12, 12, 输出 ((3-2)*12) + 12.

            输入5, 5, 5, 2, 输出-1.

    问题分析

    这个题目似乎没有好的算法,只能暴力搜索。

        首先对于所有给个数字进行全排列,总过有$A_4^4 = 24$中排列方式;

        然后对于每一种排列方式,需要添加三个运算符,每个运算符有加减乘除四种选择,总共有$4*4*4 = 64$中可能

        最后对于得到的表达式进行加括号以改变优先级,总共只有5种加括号的方式:

    • (A @ B)@(C@D);
    • (A@(B@C))@D;
    • ((A@B)@C)@D;
    • A((B@C)@D);
    • A@(B@(C@D));

    因而所有可能的情况有 $24 * 64 * 5 = 7680$种选择。

    定义子函数int calcluateBinaryExpression(int a, int b, char op) 来计算 a op b 的值;主函数首先do{}while(next_permutation)以获得所有的全排列过程,对于每个排列a, b, c, d,对于每一种加括号方式按照括号优先级计算表达式的值,判断是否等于24, 如果等于,直接return,否则,判断下一种加括号的方式。

    注意:对于op == '/', a / b 时,需要保证 b != 0 && a % b == 0。如果不满足该条件,则直接进行下一轮循环。

    程序源码

      1 #include <iostream>
      2 #include <string>
      3 #include <vector>
      4 #include <algorithm>
      5 #include <functional>
      6 #include <cstdio>
      7 #include <cstdlib>
      8 #include <cassert>
      9 using namespace std;
     10 
     11 // given number a, b and operator ch, return eval(a ch b)
     12 int calculateBinaryExpression(int a, int b, char ch)
     13 {
     14     switch(ch)
     15     {
     16     case '+':
     17         return a + b;
     18         break;
     19     case '-':
     20         return a - b;
     21         break;
     22     case '*':
     23         return a * b;
     24         break;
     25     case '/':
     26         assert(b != 0);
     27         return a / b;
     28         break;
     29     default:
     30         cerr << "WRONG OPERATOR !" << endl;
     31         return -1;
     32         break;
     33     }
     34 }
     35 
     36 // Make 24 game
     37 // BASIC IDEA: permutation all the possible cases: A(4, 4) = 24;
     38 //             Need 3 operators: 4 * 4 * 4 = 64;
     39 //             All five possible adding parenthese:
     40 //             (1) (A @ B) @ (C @ D)
     41 //             (2) (A @ (B @ C) ) @ D
     42 //             (3) ( (A @ B) @ C) @ D
     43 //             (4) A @ ( ( B @ C) @ D)
     44 //             (5) A @ ( B @ (C @ D) )
     45 //             Total Possible cases: 24 * 64 * 5 = 7680, Brute Force 
     46 // Input:  4 numbers in [1, 13], 
     47 //         use '+','-','*','/' and '(',')' to make 24
     48 // Output: If it is possible to make 24, output the expression
     49 //         Else return -1;
     50 // Notice: When calcalute x / y, need to assert (y != 0 && x % y == 0)
     51 //         If Not, continue
     52 string make24(int num1, int num2, int num3, int num4)
     53 {
     54     vector<int> v(4, 0);
     55     v[0] = num1; v[1] = num2; v[2] = num3; v[3] = num4;
     56     sort(v.begin(), v.end());
     57 
     58     string ops("+-*/");
     59 
     60     do 
     61     {
     62         // The first parenthesis
     63         // (A @ B) @ (C @ D)
     64         for (size_t i = 0; i < ops.size(); ++i)
     65         {
     66             // A @ B
     67             char op1 = ops[i];
     68             if (op1 == '/' && (v[1] == 0 || v[0] % v[1] != 0)) continue;
     69             int ans1 = calculateBinaryExpression(v[0], v[1], op1);
     70             for (size_t j = 0; j < ops.size(); ++j)
     71             {
     72                 // C @ D
     73                 char op2 = ops[j];
     74                 if (op2 == '/' && (v[3] == 0 || v[2] % v[3] != 0)) continue;
     75                 int ans2 = calculateBinaryExpression(v[2], v[3], op2);
     76 
     77                 for (size_t k = 0; k < ops.size(); ++k)
     78                 {
     79                     // (A @ B) @ (C @ D)
     80                     char op3 = ops[k];
     81                     if (op3 == '/' && (ans2 == 0 || ans1 % ans2 != 0)) continue;
     82                     int ans = calculateBinaryExpression(ans1, ans2, op3);
     83                     if (ans == 24)
     84                     {
     85                         string str;
     86                         str.push_back('(');
     87                         str += to_string((long long)(v[0]));
     88                         str.push_back(op1);
     89                         str += to_string((long long)(v[1]));
     90                         str.push_back(')');
     91                         str.push_back(op3);
     92                         str.push_back('(');
     93                         str += to_string((long long)(v[2]));
     94                         str.push_back(op2);
     95                         str += to_string((long long)(v[3]));
     96                         str.push_back(')');
     97                         return str;
     98                     }
     99                 }
    100             }
    101             
    102         }
    103 
    104         // The second parethesis
    105         // (A op2 (B op1 C)) op3 D
    106         for (size_t i = 0; i < ops.size(); ++i)
    107         {
    108             char op1 = ops[i];
    109             if (op1 == '/' && (v[2] == 0 || v[1] % v[2] != 0)) continue;
    110             int ans1 = calculateBinaryExpression(v[1], v[2], op1);
    111             for (size_t j = 0; j < ops.size(); ++j)
    112             {
    113                 char op2 = ops[j];
    114                 if (op2 == '/' && (ans1 == 0 || v[0] % ans1 != 0)) continue;
    115                 int ans2 = calculateBinaryExpression(v[0], ans1, op2);
    116                 for (size_t k = 0; k < ops.size(); ++k)
    117                 {
    118                     char op3 = ops[k];
    119                     if (op3 == '/' && (v[3] == 0 || ans2 % v[3] != 0)) continue;
    120                     int ans = calculateBinaryExpression(ans2, v[3], op3);
    121                     if (ans == 24)
    122                     {
    123                         string str;
    124                         str.push_back('(');
    125                         str += to_string((long long)v[0]);
    126                         str.push_back(op2);
    127                         str.push_back('(');
    128                         str += to_string((long long)v[1]);
    129                         str.push_back(op1);
    130                         str += to_string((long long)v[2]);
    131                         str.push_back(')');
    132                         str.push_back(')');
    133                         str.push_back(op3);
    134                         str += to_string((long long)v[3]);
    135                         return str;
    136                     }
    137                 }
    138             }
    139         }
    140 
    141         // The third parentheses
    142         // ( ( A op1 B) op2 C) op3 D
    143         for (size_t i = 0; i < ops.size(); ++i)
    144         {
    145             char op1 = ops[i];
    146             if (op1 == '/' && (v[1] == 0 || v[0] % v[1] != 0)) continue;
    147             int ans1 = calculateBinaryExpression(v[0], v[1], op1);
    148             for (size_t j = 0; j < ops.size(); ++j)
    149             {
    150                 char op2 = ops[j];
    151                 if (op2 == '/' && (v[2] == 0 || ans1 % v[2] != 0)) continue;
    152                 int ans2 = calculateBinaryExpression(ans1, v[2], op2);
    153                 for (size_t k = 0; k < ops.size(); ++k)
    154                 {
    155                     char op3 = ops[k];
    156                     if (op3 == '/' && (v[3] == 0 || ans2 % v[3] != 0)) continue;
    157                     int ans = calculateBinaryExpression(ans2, v[3], op3);
    158                     if (ans == 24)
    159                     {
    160                         string str("((");
    161                         str += to_string((long long)v[0]);
    162                         str.push_back(op1);
    163                         str += to_string((long long)v[1]);
    164                         str.push_back(')');
    165                         str.push_back(op2);
    166                         str += to_string((long long)v[2]);
    167                         str.push_back(')');
    168                         str.push_back(op3);
    169                         str += to_string((long long)v[4]);
    170                         return str;
    171                     }
    172                 }
    173             }
    174         }
    175 
    176         // The fourth parentheses
    177         // A op3 ( ( B op1 C ) op2 D)
    178         for (size_t i = 0; i < ops.size(); ++i)
    179         {
    180             char op1 = ops[i];
    181             if (op1 == '/' && (v[2] == 0 || v[1] % v[2] != 0)) continue;
    182             int ans1 = calculateBinaryExpression(v[1], v[2], op1);
    183             for (size_t j = 0; j < ops.size(); ++j)
    184             {
    185                 char op2 = ops[j];
    186                 if (op2 == '/' && (v[3] == 0 || ans1 % v[3] != 0)) continue;
    187                 int ans2 = calculateBinaryExpression(ans1, v[3], op2);
    188                 for (size_t k = 0; k < ops.size(); ++k)
    189                 {
    190                     char op3 = ops[k];
    191                     if (op3 == '/' && (ans2 == 0 || v[0] % ans2 != 0)) continue;
    192                     int ans = calculateBinaryExpression(v[0], ans2, op3);
    193                     if (ans == 24)
    194                     {
    195                         string str;
    196                         str += to_string((long long)v[0]);
    197                         str.push_back(op3);
    198                         str += "((";
    199                         str += to_string((long long)v[1]);
    200                         str.push_back(op1);
    201                         str += to_string((long long)v[2]);
    202                         str.push_back(')');
    203                         str.push_back(op2);
    204                         str += to_string((long long)v[3]);
    205                         str.push_back(')');
    206                         return str;
    207                     }
    208                 }
    209             }
    210         }
    211         
    212         // The fifth parenthese
    213         // A op3 ( B op2 ( C op1 D) );
    214         for (size_t i = 0; i < ops.size(); ++i)
    215         {
    216             char op1 = ops[i];
    217             if (op1 == '/' && (v[3] == 0 || v[2] % v[3] != 0)) continue;
    218             int ans1 = calculateBinaryExpression(v[2], v[3], op1);
    219             for (size_t j = 0; j < ops.size(); ++j)
    220             {
    221                 char op2 = ops[j];
    222                 if (op2 == '/' && (ans1 == 0 || v[1] % ans1 != 0)) continue;
    223                 int ans2 = calculateBinaryExpression(v[1], ans1, op2);
    224                 for (size_t k = 0; k < ops.size(); ++k)
    225                 {
    226                     char op3 = ops[k];
    227                     if (op3 == '/' && (ans2 == 0 || v[0] % ans2 != 0)) continue;
    228                     int ans = calculateBinaryExpression(v[0], ans2, op3);
    229                     if (ans == 24)
    230                     {
    231                         string str;
    232                         str += to_string((long long)v[0]);
    233                         str.push_back(op3);
    234                         str.push_back('(');
    235                         str += to_string((long long)v[1]);
    236                         str.push_back(op2);
    237                         str.push_back('(');
    238                         str += to_string((long long)v[2]);
    239                         str.push_back(op1);
    240                         str += to_string((long long)v[3]);
    241                         str += "))";
    242                         return str;
    243                     }
    244                 }
    245             }
    246         }
    247 
    248     } while(next_permutation(v.begin(), v.end()));
    249 
    250     return "-1";
    251 }
    252 
    253 int main()
    254 {
    255     int a, b, c, d;
    256     cin >> a >> b >> c >> d;
    257     string ans = make24(a, b, c, d);
    258     cout << ans << endl;
    259     return 0;
    260 }

     参考文献

    [1] 速算24算法思路

    [2] 24 Game/Countdown/Number Game solver, but without parentheses in the answer


  • 相关阅读:
    logging模块
    获得本机时间
    为了节约一台打印机,我也是无奈呀~~~~
    django通过管理页上传图片
    python打印爱心
    djago后台管理页面
    今天休年休找不到填年休的表了,结果就写了一个查找文件的缩引存起来方便下次用
    中间件调用顺序_______网站仿问过程
    django中间件
    py3.8安装
  • 原文地址:https://www.cnblogs.com/python27/p/3843310.html
Copyright © 2020-2023  润新知