雙向搜尋是為了避免在深層子樹上浪費時間
有的問題有初態 和 終態
當我們從初態和終態雙向搜尋時,就相當已經搜尋了整個狀態空間
來看乙個例題吧
達達幫翰翰給女生送禮物,翰翰一共準備了n個禮物,其中第i個禮物的重量是g[i]。
達達的力氣很大,他一次可以搬動重量之和不超過w的任意多個物品。
達達希望一次搬掉盡量重的一些物品,請你告訴達達在他的力氣範圍內一次效能搬動的最大重量是多少。
輸入格式
第一行兩個整數,分別代表w和n。
以後n行,每行乙個正整數表示g[i]。
輸出格式
僅乙個整數,表示達達在他的力氣範圍內一次效能搬動的最大重量。
n <= 46
w <= 2^31 - 1
我們很容易想到揹包問題,不過太大導致陣列開不了,然後n比較小
如果暴力列舉是2^46肯定超時
不過我們可以採用雙向搜尋來搞
我們可以統計前一半的所有情況,複雜度是2^23 <=1e7
然後得到的排個序,對後半部分也可以列舉每一種情況,然後在前一半找出最優解可以二分出答案
所以後半部分是2^(n/2)*log(2^n/2)
然後這題還有乙個剪枝就是對於列舉的時候超出了w就直接回溯了
還有對於前一半重複的部分去重,也可以減少很多複雜度(去重用unique函式)
然後搜尋裡必須遵循的從決策數少的開始原則,可以把禮物從大到小排序,這樣列舉的時候就使得搜尋樹深度變小了
**:
#includeusing namespace std;不過這個地方還有個優化,就是數學關係吧#define ll long long
const int n = 47;
ll g[n],a[1 << 23];
ll sum,w,ans;
int tot,n,cnt,up;
bool cmp(ll x,ll y)
void dfs1(int cur)
sum += g[cur];
if(sum <= w)
dfs1(cur + 1);
sum -= g[cur];
if(sum <= w)
dfs1(cur + 1);
}void dfs2(int cur,ll s)
else r = m - 1;
} if(s + x <= w) ans = max(ans,s + x);
return; }
if(s + g[cur] <= w) dfs2(cur + 1,s + g[cur]);
dfs2(cur + 1,s);
}int main()
由於我們前半部分是n/2 複雜度是2^(n/2), 後半部分也是n/2複雜度是2^(n/2)*(log2^(n/2)),所以總的複雜度是2^(n/2)*(log2^(n/2))
後半部分是2^(n/2)*(log2^(n/2))起決定作用
我們如果讓前面多搜兩個禮物的話 複雜度變為
2^(n/2 + 2)*(log2^(n/2 - 2)是小於2^(n/2)*(log2^(n/2))的使前後的複雜度均衡了
#includeusing namespace std;事實證明確實如此#define ll long long
const int n = 47;
ll g[n],a[1 << 23];
ll sum,w,ans;
int tot,n,cnt,up;
bool cmp(ll x,ll y)
void dfs1(int cur)
sum += g[cur];
if(sum <= w)
dfs1(cur + 1);
sum -= g[cur];
if(sum <= w)
dfs1(cur + 1);
}void dfs2(int cur,ll s)
else r = m - 1;
} if(s + x <= w) ans = max(ans,s + x);
return; }
if(s + g[cur] <= w) dfs2(cur + 1,s + g[cur]);
dfs2(cur + 1,s);
}int main()
學到了
雙向寬度搜尋
從正反兩個方向進行寬度優先搜搜,可以大大減少搜尋量,提高搜尋速度。從初始狀態和目標狀態兩個方向同時進行擴充套件,如果兩顆解答樹在某個節點第一次發生重合,即可終止此搜尋過程,則該節點所連線的兩條路徑所拼成的路徑就是最優解。通常有兩種搜尋方式 1.兩個方向交替擴充套件 2.選擇節點個數較少的那個方向先擴...
折半列舉(雙向搜尋)
各有n個整數的四個數列a b c d。要從每個數列中各取乙個數,使四個數的和為0。求出這樣組合的個數。輸入n 6 a b c d 從4個數列中選擇共有n4種情況,全部判斷一遍不可行。不過將它們對半分成ab和cd再考慮,就可以快速解決了。從2個數列中選擇的話只有n2種組合,所以可以進行列舉。先從a b...
迭代加深和雙向搜尋
當答案的層數較低,並且搜尋的分支較多時,如果直接搜尋會消耗很多時間。這時候可以進行多次搜尋,每次搜尋可以限制乙個深度,如果我們在當前深度下搜尋不到答案,就增加深度限制,重新搜尋一邊答案,這樣 迭代 且 加深 的過程稱為迭代加深。但他的缺點也很明顯,每次需要重新搜尋一遍,所以在答案的層數比較深的時候不...