多重揹包可行性
阿新 • • 發佈:2018-12-16
分析
雖然用樸素的多重揹包加二進位制拆分能卡過去,但時間複雜度應該是錯誤的
我們還是來講一下O(n*m)的演算法
由於這道題只要求了可行性(也就是面值能否被拼湊出來)
那麼我們分析一下,發現一個面值能被拼湊出來當前僅當
- 前i-1種硬幣已經拼出來
- 使用了第i種硬幣,且j-a[i]已經拼湊出來了
程式碼
#include<cstdio> #include<iostream> #include<cstring> #define in read() #define ll long long using namespace std; inline int read(){ char ch;int f=1,res=0; while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1; while(ch>='0'&&ch<='9'){ res=(res<<3)+(res<<1)+ch-'0'; ch=getchar(); } return f==1?res:-res; } int a[105],c[105],m,n,cnt[100009]; bool f[100009]; int main(){ while(1){ n=in;m=in; if(!n&&!m) break; int i,k; for(i=1;i<=n;++i) a[i]=in; for(i=1;i<=n;++i) c[i]=in; ll ans=0; memset(f,0,sizeof(f)); f[0]=1; for(i=1;i<=n;++i){ memset(cnt,0,sizeof(cnt)); for(k=a[i];k<=m;++k){//attention if(!f[k]&&f[k-a[i]]&&cnt[k-a[i]]<c[i]) { f[k]=1;cnt[k]=cnt[k-a[i]]+1; ans++; } } } cout<<ans<<'\n'; } return 0; }
雖然 k 迴圈那裡我們使用了完全揹包的想法,但cnt[]就可以限制使用個數,符合多重揹包