P4799 [CEOI2015 Day2]世界冰球錦標賽
阿新 • • 發佈:2020-12-13
\(0-1\)揹包解法
適用資料範圍:\(N≤40,M≤10^6\)
狀態表示:\(f(i,j)\):從前\(i\)個物品中選,花費不超過(小於等於)\(j\)的方案數。
最後累加\(f(n,0~m)\)即可。
const int N=45,M=1e6+10; LL price[N]; LL f[M]; LL n,m; LL ans; int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>price[i]; f[0]=1; for(int i=1;i<=n;i++) { for(int j=m;j>=price[i];j--) { f[j]+=f[j-price[i]]; } } for(int i=0;i<=m;i++) ans+=f[i]; cout<<ans<<endl; //system("pause"); }
折半搜尋——正解
我們可以將所有比賽分成兩部分,對這兩部分分別進行指數型列舉,然後使用vector來儲存搜尋過程中產生的可能的花費。
最後再將兩部分進行合併,得出最終的答案。
時間複雜度:\(O(2^{\frac{n}{2}}log2^{\frac{n}{2}})\)
const int N=45; LL price[N]; vector<LL> suml; vector<LL> sumr; LL n,m; LL ans; void dfs(int l,int r,LL sum,vector<LL> &v) { if(l>r) { v.pb(sum); return; } if(sum + price[l] <= m) dfs(l+1,r,sum+price[l],v); dfs(l+1,r,sum,v); } int main() { cin>>n>>m; for(int i=0;i<n;i++) cin>>price[i]; dfs(0,n/2-1,0,suml); dfs(n/2,n-1,0,sumr); sort(suml.begin(),suml.end()); for(int i=0;i<sumr.size();i++) { ans+=upper_bound(suml.begin(),suml.end(),m-sumr[i])-suml.begin(); } cout<<ans<<endl; //system("pause"); }