poj 1742 多重背包可行性
简单的方法来自http://poj.org/showmessage?message_id=156697
#include<stdio.h> #include<string.h> int dp[100010]; int num[110],v[110]; int used[100010]; int main(){ int n,m,i,j; while(scanf("%d%d",&n,&m),(n||m)){ for(i=0;i<n;i++) scanf("%d",&v[i]); for(i=0;i<n;i++) scanf("%d",&num[i]); memset(dp,0,sizeof(dp)); dp[0]=1; int ans=0; for(i=0;i<n;i++){ memset(used,0,sizeof(used)); for(j=v[i];j<=m;j++){ if(!dp[j]&&dp[j-v[i]]&&used[j-v[i]]<num[i]){ ans++; dp[j]=1; used[j]=used[j-v[i]]+1; } } } printf("%d\n",ans); } return 0; }
多重背包倍增
#include<cstdio> using namespace std; const int mm=111111; const int mn=111; int a[mn],c[mn]; bool f[mm]; int n,m; void CompletePack(int v) { for(int i=v;i<=m;++i)f[i]|=f[i-v]; } void ZeroOnePack(int v) { for(int i=m;i>=v;--i)f[i]|=f[i-v]; } int main() { int i,j,ans; while(scanf("%d%d",&n,&m),n+m) { for(i=0;i<n;++i)scanf("%d",&a[i]); for(i=0;i<n;++i)scanf("%d",&c[i]); for(i=f[0]=1;i<=m;++i)f[i]=0; for(i=0;i<n;++i) if(c[i]) if(c[i]*a[i]>=m)CompletePack(a[i]); else { j=1; while(j<c[i]) { ZeroOnePack(a[i]*j); c[i]-=j; j<<=1; } ZeroOnePack(a[i]*c[i]); } ans=0; for(i=1;i<=m;++i)ans+=f[i]; printf("%d\n",ans); } return 0; }