试题分析
我们发现此题是一个十分简单的多重背包。但是按照朴素写法会超时。所以要去考虑优化。
我们发现我们若$W=7$,可以拆成$1+2+4$,不用每次$1+1+1+1+1+1+1$,从$N$级就变成$log$级了。所以对于每一组$(w_i,c_i)$,我们都可以拆成多个二进制数,然后暴力去写即可。
时间复杂度:$O(k imes sum_{i=1}^n log_2 C_i).$
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int N=1e6+1; int n,w[N],c[N],f[N],k,W[N]; void solve(int wi,int ci,int numi){ int t=1; while(numi>=t){ w[++w[0]]=wi*t; c[++c[0]]=t; numi-=t; t<<=1; } w[++w[0]]=wi*numi; c[++c[0]]=numi; return; } int main(){ n=read(); for(int i=1;i<=n;i++) W[i]=read(); for(int i=1;i<=n;i++){ int num=read(); solve(W[i],1,num); } memset(f,127/3,sizeof(f));f[0]=0; k=read();n=w[0]; for(int i=1;i<=n;i++) for(int j=k;j>=w[i];j--) f[j]=min(f[j],f[j-w[i]]+c[i]); cout<<f[k]; }