luogu||P1776||宝物筛选||多重背包||dp||二进制优化

题目描述

终于,破解了千年的难题。小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;
}

猜你喜欢

转载自www.cnblogs.com/supersumax/p/9418388.html