题目描述
终于,破解了千年的难题。小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物。看来小FF只能含泪舍弃其中的一部分宝物了……小FF对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小FF有一个最大载重为W的采集车,洞穴里总共有n种宝物,每种宝物的价值为v[i],重量为w[i],每种宝物有m[i]件。小FF希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。
思路
典型的多重背包+二进制优化dp,看过背包九讲以后来水一波题,看到网上很多神犇利用左移右移来进行优化,我只能Orz,我先使用预处理,反正数字利用二进制优化以后不会太大,预处理到2^30,将物品的件数分解,最后利用0/1背包的模板输出答案,代码如下
#include<iostream> #include<cstring> #include<algorithm> #include<ctime> #include<cmath> #include<iomanip> using namespace std; const int maxn=666666; int n,max_weight; int ans=0; int f[maxn],weight[maxn],nums[maxn],values[maxn]; int k2[50],k2s[50]; void prem()//处理2^k { int sum=2; k2[1]=1;k2s[1]=1;k2s[0]=0; for(int i=2;i<=30;i++) { k2[i]=k2[i-1]*2; k2s[i]=k2s[i-1]+k2[i]; } } int prek(int m)//处理系数 { for(int i=1;i<=m;i++) { if(m==1) return 0; if(m==2) return 1; if(m<k2[i]) return i-1; } } int sum=0; void input() { cin>>n>>max_weight; for(int i=1;i<=n;i++) { int aa,bb,cc; cin>>aa>>bb>>cc; int temp=prek(cc); cout<<temp<<endl; for(int j=1;j<=temp-1;j++) { sum++; weight[sum]=aa; values[sum]=bb; nums[sum]=k2[j]; } cout<<k2s[temp]<<' '<<cc<<endl; //if(k2s[temp]!=cc) //{ if(temp==0) { sum++; weight[sum]=aa;values[sum]=bb; nums[sum]=cc; } else { sum++; weight[sum]=aa;values[sum]=bb; nums[sum]=cc-k2[temp]+1; /* sum++; weight[sum]=aa;values[sum]=bb; nums[sum]=cc-k2[temp]+1; */ } } //cout<<"*********************************"<<endl; /* for(int i=1;i<=sum;i++) { cout<<weight[i]<<' '<<values[i]<<' '<<nums[i]<<endl; } */ } void solve() { for(int i=1;i<=sum;i++) for(int j=max_weight;j>=weight[i];j--) { f[j]=max(f[j],f[j-weight[i]]+values[i]); } cout<<f[max_weight]; } int main() { prem(); input(); solve(); return 0; }