C++-算24 解題思路
阿新 • • 發佈:2022-03-20
【Horn Studio】程式設計專欄: 算24 解題思路
題目
題目描述
給出4個小於10個正整數,你可以使用加減乘除4種運算以及括號把這4個數連線起來得到一個表示式。現在的問題是,是否存在一種方式使得得到的表示式的結果等於24。這裡加減乘除以及括號的運算結果和運算的優先順序跟我們平常的定義一致(這裡的除法定義是實數除法)。
比如,對於5,5,5,1,我們知道5 * (5 – 1 / 5) = 24,因此可以得到24。又比如,對於1,1,4,2,我們怎麼都不能得到24。
輸入
輸入資料包括多行,每行給出一組測試資料,包括4個小於10個正整數。最後一組測試資料中包括4個0,表示輸入的結束,這組資料不用處理。輸出
樣例輸入
5 5 5 1
1 1 4 2
0 0 0 0
樣例輸出
YES
NO
思路
1.n 個數算 24,必有兩個數先算。這兩個數算的結果,和剩餘 n-2 個數,就構成了 n-1 個數求 24 的問題。
2.列舉先算的兩個數,以及這兩個數的運算方式。
不同於以嘗的DP,此題是一道dfs,如果使用暴力搜檢,求出每一種得數………………(寫不寫得出來先不說,你能寫出來,沒個300000000000000000000000億萬行是不可能的!),此處不可能使用此方法。因此,我們的思路巧妙一點……
不妨我們把它隨即計算,最後只剩下一個數,看這個數是不是24
(吃瓜群眾:萬一這個隨機沒有準確計算出那個正確方式,豈不還是青草池塘處處WA?)不用怕!會列舉到每個的!
程式碼實現起來也就很EASY了,且大部分程式碼改個符號CV過來,不愁沒發!
程式碼
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 double a[5] = {0}; 5 #define EPS 1e-6 6 7 int isZero(double x) 8 { 9 return fabs(x) <= EPS; 10 } 11 12 int count24(double a[], int n) 13 { 14 double b[5] = {0}; 15 if (n == 1) { 16 if (isZero(a[0] - 24)) { 17 return 1; 18 } else { 19 return 0; 20 } 21 } 22 for (int i = 0; i < n - 1; i++) { 23 for (int j = i + 1; j < n; j++) { 24 int m = 0; 25 for (int k = 0; k < n; ++k) 26 if ( k != i && k != j ) 27 b[m++] = a[k]; 28 b[m] = a[i] + a[j]; 29 if ( count24(b, m + 1) ) 30 return 1; 31 b[m] = a[i] - a[j]; 32 if ( count24(b, m + 1) ) 33 return 1; 34 b[m] = a[j] - a[i]; 35 if ( count24(b, m + 1) ) 36 return 1; 37 b[m] = a[i] * a[j]; 38 if ( count24(b, m + 1) ) 39 return 1; 40 if ( !isZero(a[j]) ) { 41 b[m] = a[i] / a[j]; 42 if (count24(b, m + 1)) 43 return 1; 44 } 45 if ( !isZero(a[i]) ) { 46 b[m] = a[j] / a[i]; 47 if ( count24(b, m + 1) ) 48 return 1; 49 } 50 } 51 } 52 return 0; 53 } 54 55 int main() 56 { 57 while (true) { 58 int s = 0; 59 for (int i = 0; i < 4; i++) { 60 scanf("%lf", &a[i]); 61 s += a[i]; 62 } 63 if (s == 0) { 64 return 0; 65 } 66 if (count24(a, 4)) { 67 printf("YES\n"); 68 } else { 69 printf("NO\n"); 70 } 71 } 72 return 0; 73 }
彩蛋
:程式碼不多,也就五六十行而已