【アルゴリズム29】速算24

47626 ワード

問題の説明
出典:PAT ds 2-08
4つの数字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$の配列
次に、各配列について、3つの演算子を追加する必要があります.各演算子には4つの選択肢があり、合計$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