原题: http://codeforces.com/contest/1132/problem/E
题意: 有 个1, 个2…… 个8,问大小为 背包可以装下的最大 。 ,
解析:
虽然每个数的数量很大,但是局限于只有8种数,所以组合的重复率会很高。
怎么说?1到8的LCM为840,当2的数量大于等于420时,我们只需要记录下1,8的数量大于等于120时,也记录下1。这个1可以在不同的方案中起到相同的作用。
再想一下,420个2可以记录下来,但是419个2和1个3能不能记录下1,再转移到状态1呢?显然不行。之前记录下1是因为状态 可以通过加减 个 来转移到相邻的状态 ,而419个2和1个3就不行。
如果用 表示到了第 个数,状态为 时的最大840个数。那么通过上面的结果可以得出:(共 个 ,选出 个 )
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL dp[10][10000];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
LL w;cin>>w;
LL v;
memset(dp,0xc0,sizeof(dp));
dp[0][0]=0;
LL ma=8*840;
for(LL i=1;i<=8;i++){
cin>>v;
for(LL j=0;j<ma;j++){
for(LL k=min((840/i)-1ll,v);k>=0;k--){
if(dp[i-1][j]>=0)
dp[i][j+k*i]=max(dp[i][j+k*i],dp[i-1][j]+(v-k)/(840/i));
}
}
}
LL ans=-1;
for(LL i=0;i<min(ma,w+1);i++){
if(dp[8][i]>=0)
ans=max(ans,i+840*min(dp[8][i],w>=i?(w-i)/840:0));
}
cout<<ans<<endl;
}