n 个物品 背包体积m
n 个物品的价值 n 个物品的数目
参考http://www.cnblogs.com/xinsheng/archive/2013/12/04/3458362.html
分3种情况
1 个数只有1个 显然是0 1 n*c
2 价值*数目>m 完全背包 n*c
3 用队列优化 这边好像不是单调队列
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> #include<iterator> #include<stack> using namespace std; #define ll __int64 #define MAXN 100010 #define inf 2000000007 #define mod 1000000007 int a[MAXN],c[MAXN]; bool dp[MAXN],q[MAXN]; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n+m==0) break; memset(dp,0,sizeof(dp)); memset(q,0,sizeof(q)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&c[i]); dp[0]=1; for(int i=1;i<=n;i++) { if(c[i]==1) { for(int j=m;j>=a[i];j--) if(dp[j-a[i]]) dp[j]=1; } else if(a[i]*c[i]>=m) { for(int j=a[i];j<=m;j++) if(dp[j-a[i]]) dp[j]=1; } else { for(int j=0;j<a[i];j++)//列举每个余下来的 { int sum=0,st=0,en=-1; for(int v=j;v<=m;v+=a[i])//这边显然是从这个余下来的数 然后去放物品 { if(en-st==c[i])//物品数超过了 sum-=q[st++]; q[++en]=dp[v];//进去 sum+=dp[v]; //里面个数 if(sum) //显然要里面有满足条件的 恰好这个或者前面有满足的 dp[v]=1; } } } } int cnt=0; for(int i=1;i<=m;i++) if(dp[i]) cnt++; printf("%d ",cnt); } return 0; }