1. 程式人生 > >抽簽問題(不斷優化)

抽簽問題(不斷優化)

得到 turn for () clas 判斷 spa 存在 alt

問題描述:

假設存在n個簽,通過抽取四次,如果四次抽取的和為m即勝利。

初始解:

 1 for(int a = 0; a < n; a++)
 2 {
 3     for(int b = 0; b < n; b++)
 4     {
 5         for(int c = 0; c < n; c++)
 6         {
 7             for(int d = 0; d < n; d++)
 8             {
 9                 if(k[a] + k[b] + k[c] + k[d] == m)
10                     f = true
; 11 } 12 } 13 } 14 }

難度增加,將n的限制條件為1~1000,此時,四重循環明顯復雜度過高,需改進算法。

上面所記載的程序的循環部分。最內側關於d的循環所做的事就是

檢查是否有d使得技術分享圖片

通過對式子移項,就能得到另一種表達式

檢查是否有d使得技術分享圖片

就是說,檢查數組k中所有元素,判斷是否有技術分享圖片

結合二分搜索進行求解,註意二分搜索前提為該數組排好序(可用c++自帶的binary_serach)

技術分享圖片

 1 int n, m, k[MAX_N];
 2 
 3 bool binary_serach(int x)
 4 {
 5     int l = 0
, r = n; 6 while(r - 1 >= 1) 7 { 8 int i = (l + r) / 2; 9 if(k[i] == x) 10 return true; 11 else if(k[i] < x) 12 l = i + 1; 13 else 14 r = i; 15 } 16 return false; 17 } 18 19 void solve() 20 { 21 sort(k, k + n);
22 bool f = false; 23 for(int a = 0; a < n; a++) 24 { 25 for(int b = 0; b < n; b++) 26 { 27 for(int c = 0; c < n; c++) 28 { 29 if(binary_serach(m - k[a] - k[b] - k[c])) 30 { 31 f = true; 32 } 33 } 34 } 35 } 36 if(f) 37 cout << "Yes" << endl; 38 else 39 cout << "No" << endl; 40 }

技術分享圖片的算法

著眼於內層的兩個循環

檢查是否有c和d使得技術分享圖片

這種情況並不能直接使用二分搜索。但是,如果預先枚舉出技術分享圖片所得的技術分享圖片個數字並排好序,便可以利用二分搜索了。

 1 int n, m, k[MAX_N];
 2 int kk[MAX_N * MAX_N];
 3 bool binary_serach(int x)
 4 {
 5     int l = 0, r = n * n;
 6     while(r - 1 >= 1)
 7     {
 8         int i = (l + r) / 2;
 9         if(kk[i] == x)
10             return true;
11         else if(kk[i] < x)
12             l = i + 1;
13         else
14             r = i;
15     }
16     return false;
17 }
18 
19 void solve()
20 {
21     for(int c = 0; c < n; c++)
22     {
23         for(int d = 0; d < n; d++)
24         {
25             kk[c * n + d] = k[c] + k[d];
26         }
27     }
28     
29     sort(kk, kk + n * n);
30     for(int a = 0; a < n; a++)
31     {
32         for(int b = 0; b < n; b++)
33         {
34             if(binary_serach(m - k[a] - k[b]))
35             {
36                 f = true;
37             }
38         }
39     }
40     if(f)
41         cout << "Yes" << endl;
42     else
43         cout << "No" << endl;
44 }

抽簽問題(不斷優化)