1. 程式人生 > >hdu2844 Coins -----多重背包+二進制優化

hdu2844 Coins -----多重背包+二進制優化

解決 題目 pan 如果 組合 name 數量 快速 情況

題目意思:給出你n種硬幣的面額和數量,詢問它能夠組合成1~m元中的幾種情況。

這題如果直接按照完全背包來寫的話,會因為每一種硬幣的數目1 ≤ Ci ≤ 1000而超時,所以這裏需要運用二進制優化來解決問題。

二進制優化和快速冪的思路是一樣的。

例如:面值為1的硬幣有20枚,如果完全背包的話就需要20次狀態轉移。

運用二進制優化後,就變成了 面值為1的硬幣1枚、面值為2的硬幣1枚、面值為4的硬幣1枚、面值為8的硬幣1枚,最後多出的5個,就直接作為面值為5的硬幣一枚,加入新的數組中。之前的20次轉移就被優化成了5次。在極限數據1000的情況下優化的更多。

以下為詳細代碼:

#include<iostream>
#include
<string.h> using namespace std; int n,m,i,j; int a[100050],c[100050],s[100050],dp[100050]; int ys=0; int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; ys=0; for(i=0;i<n;i++) scanf("%d",&a[i]); for(i=0;i<n;i++) scanf("%d
",&c[i]); for(i=0;i<n;i++) { int k=1; int p=c[i]; while(p>k) { s[ys]=a[i]*k; ys++; p-=k; k*=2; } s[ys++]=a[i]*p; }
//for(i=0;i<ys;i++) cout<<s[i]<<" ";cout<<endl; for(i=0;i<=m;i++) dp[i]=0; for(i=0;i<ys;i++) for(j=m;j>=s[i];j--) { dp[j]=max(dp[j],dp[j-s[i]]+s[i]); } int ans=0; for(i=1;i<=m;i++) { // cout<<dp[i]<<endl; if(dp[i]==i) ans++; } cout<<ans<<endl; } }

hdu2844 Coins -----多重背包+二進制優化