折半搜尋 meet in the middle

2021-10-02 16:34:18 字數 2039 閱讀 9522

在使用搜尋的時候,當n過大2n會超時,這時候可以用折半搜尋,把時間複雜度降低到2n/2+1

具體方法:分別搜尋前一半,把狀態放入a陣列,搜尋後一半,把狀態放入b陣列,最後統計答案。

一般meet in the middle的難點主要在於最後答案的組合統計。

我們可以現將a或b陣列sort,讓其有序。然後通過列舉另乙個陣列中的狀態,來實現統計答案。

題目鏈結

題意:給定n(<=40)場比賽門票各自的**,和bobek擁有的錢數,求觀賽方案總數。

(如果存在以其中一種方案**某場比賽而另一種方案不**,則認為這兩種方案不同。可以一場也不看)

思路:240的搜尋肯定會超時,所以折半搜尋。

#include

using namespace std;

#define ll long long

const

int maxn=

1<<21;

ll m,ans,a[50]

,suma[maxn]

,sumb[maxn]

;int n,cnta,cntb;

void

dfs(

int t,

int m,ll f[

],ll s,

int&cnt)

dfs(t+

1,m,f,s,cnt)

;dfs

(t+1

,m,f,s+a[t]

,cnt);}

intmain()

cout<

}

題目鏈結

題意:給n(<=20)個數,從中任意選出一些數,使這些數能分成和相等的兩組。求有多少種選數的方案。

思路:這道題有三種狀態:①不放入任何集合 ②放入左邊集合 ③放入右邊集合

[面向題解設計程式。。一知半解]

#include

#include

#include

#include

#include

using namespace std;

#define ll long long

int n,mid;

struct nodesuma[

1<<22]

,sumb[

1<<22]

;int cnta,cntb,m[44]

,r;bool vis[

1<<23]

;ll ans;

void

dfs(

int l,

int flag,

int sum,

int t)

else

return;}

dfs(l+

1,flag,sum,t)

;dfs

(l+1

,flag+(1

<<

(l-1))

,sum+m[l]

,t);

dfs(l+

1,flag+(1

<<

(l-1))

,sum-m[l]

,t);

}inline bool cmp1

(node x,node y)

inline bool cmp2

(node x,node y)

intmain()

r++;}

if(l

.v==suma[l+1]

.v)r=p;

l++;}

cout<

}

poj 折半搜尋

題意 給你乙個含有n n 1000 個數的數列,問這個數列中是否存在四個不同的數a,b,c,d,使a b c d 若存在則輸出最大的d 思路 完全暴力的話o n 4 會t,可以考慮雙向搜尋,公式變形為a b d c 分別列舉a b和c d,將值和下標存在結構體中,再二分查詢即可 include in...

折半搜尋 某種密碼

某種密碼 描述關於某種密碼有如下描述 某種密碼的原文a是由n個數字組成,而密文b是乙個長度為n的01數串,原文和密文的關聯在於乙個鑰匙碼key。若key ai bi key ai bi 則密文就是原文的一組合法密碼。現在有原文和鑰匙碼,請編乙個程式來幫助他統計到底有多少個符合條件的密文。輸入第一行兩...

折半列舉(雙向搜尋)

各有n個整數的四個數列a b c d。要從每個數列中各取乙個數,使四個數的和為0。求出這樣組合的個數。輸入n 6 a b c d 從4個數列中選擇共有n4種情況,全部判斷一遍不可行。不過將它們對半分成ab和cd再考慮,就可以快速解決了。從2個數列中選擇的話只有n2種組合,所以可以進行列舉。先從a b...