学了种很快的新方法,就是每次填f[j]时直接由f[j-weight[i]]推出,前提是num[j - weight[i]]<used[i]
num每填一行都要清零,num[j]表示当前物品填充j大小的包需要至少使用多少个
num每填一行都要清零,num[j]表示当前物品填充j大小的包需要至少使用多少个
PS:单调队列和位运算优化http://www.snowoat.tk/?p=161
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#define CL(a,b) memset(a,b,sizeof(a))
#define MIN(a,b) (a<b?a:b)
#define INF 0x7ffffff
using namespace std;
const int M(100010);
const int N(110);
int f[M],a[N],v[N],used[M];
int main()
{
int m,n,i,j,k;
while(scanf("%d%d",&n,&m)!=EOF&&(n+m))
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
CL(f,0);
for(i=0;i<n;i++)
scanf("%d",&v[i]);
int t;
/* m--;
sum=MIN(sum,m);
for(i=0;i<n;i++)
{
j=1;
while(j<=a[i])
{
t=j*v[i];
for(k=sum;k>=t;k--)
f[k]=MAX(f[k],f[k-t]+t);
a[i]-=j;
j<<=1;
}
t=a[i]*v[i];
for(k=sum;k>=t;k--)
f[k]=MAX(f[k],f[k-t]+t);
}
t=0;
for(i=1;i<=sum;i++)
{
// printf("(%d,%d)",i,f[i]);
if(f[i]==i)
t++;
}*/
f[0]=1;
for(i=0;i<n;i++)
{
CL(used,0);
for(j=a[i];j<=m;j++)
{
int num=j-a[i];
if(!f[j]&&f[num]&&used[num]<v[i])
{
f[j]=1;used[j]=used[num]+1;
}
}
}
t=0;
for(i=1;i<=m;i++)
if(f[i])
t++;
printf("%d\n",t);
}
}
//单调队列优化
#include"iostream"
using namespace std;
int main()
{
int n,m;
int A[100],C[100];
char dp[100010];
while(scanf("%d%d",&n,&m)&&n!=0&&m!=0)
{
for(int i=0;i<n;i++)
scanf("%d",&A[i]);
for(int i=0;i<n;i++)
scanf("%d",&C[i]);
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=0;i<n;i++)
{
if(A[i]>m)
continue;
if(A[i]*C[i]>=m)
for(int j=A[i];j<=m;j++)dp[j]=dp[j]|dp[j-A[i]];
else
{
int t=A[i]*C[i];
for(int j=0;j<A[i];j++)
{
int sum=0,x=m-j;
//用C[i]循环出错,虽然A[i]*C[i]<m但是可能A[i]*C[i]+A[i]-1>=m
for(;x>=max(0,m-j-t);x-=A[i]){sum+=dp[x];}
for(int k=m-j;k>0;k-=A[i])
{
sum-=dp[k];dp[k]=sum>0||dp[k];
if(x>=0){
sum+=dp[x];x-=A[i];
}
}
}
}
}
int cnt=0;
for(int i=1;i<=m;i++)
if(dp[i])cnt++;
cout<<cnt<<endl;
}
}
//位运算优化
#include"iostream"
using namespace std;
int main()
{
int n,m;
int A[100],C[100];
char dp[100010];
while(scanf("%d%d",&n,&m)&&n!=0&&m!=0)
{
for(int i=0;i<n;i++)
scanf("%d",&A[i]);
for(int i=0;i<n;i++)
scanf("%d",&C[i]);
memset(dp,0,m+1);
dp[0]=1;
for(int i=0;i<n;i++)
{
if(A[i]>m)
continue;
if(A[i]*C[i]>=m)
for(int j=A[i];j<=m;j++)
dp[j]=dp[j]|dp[j-A[i]];
else
{
int k=0,temp;
while((1<<k)<C[i])
{
temp=A[i]<<k;
for(int j=m;j>=temp;j--)
dp[j]=dp[j]|dp[j-temp];
C[i]-=(1<<k);
k++;
}
temp=C[i]*A[i];
for(int j=m;j>=temp;j--)
dp[j]=dp[j]|dp[j-temp];
}
}
int cnt=0;
for(int i=1;i<=m;i++)
if(dp[i])cnt++;
cout<<cnt<<endl;
}
}