P1776 宝物筛选 多重背包

题目描述

终于,破解了千年的难题。小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物。看来小FF只能含泪舍弃其中的一部分宝物了……小FF对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小FF有一个最大载重为W的采集车,洞穴里总共有n种宝物,每种宝物的价值为v[i],重量为w[i],每种宝物有m[i]件。小FF希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。

输入格式

第一行为一个整数N和w,分别表示宝物种数和采集车的最大载重。

接下来n行每行三个整数,其中第i行第一个数表示第i类品价值,第二个整数表示一件该类物品的重量,第三个整数为该类物品数量。

输出格式

输出仅一个整数ans,表示在采集车不超载的情况下收集的宝物的最大价值。

==============================================================================================================================================================

一些遇到的问题

对于二进制的理解。

不是完全背包,考虑越界问题。
M=10,c[i]=3,s[i]=26
1*
2*
4(x) 但是for循环从10->12所以不循环了。
以此类推一直搞到24,碰到边界,回到2。
假如还爆,那继续不循环
得了,我看见22行的问题了。草dp[j-c[i]]*k  -> dp[j-c[i]*k]
还错。
/*15:41*/

问题出在二进制倍增何时越界。
假定s[i]==13;
1 2 4 6
4个数字可以构成1-13内的所有数字,故可完成化简01背包问题。
若是1 2 4……2^n可以组成2^(n+1)-1内的所有数字。
所以1-7可以通过这样组成。
所以把剩下的系数得6。就扩充到1-13;


注意:k循环完后自乘
也就是k*2-1<=s[i]可以循环。 //我刚刚真是天才
譬如 1,2,4
结束后为8,如果动8,那么就满足15了。显然不需要满足15。所以k*2-1>s[i]了,就不用循环了。
/*16:25*/

#include <bits/stdc++.h>
#define MAXN 101
#define MAXM 40001
using namespace std;
int v[MAXN],c[MAXN],s[MAXN],dp[MAXM];
int main()
{
    int n,m;
    cin>>n>>m;
    for (int i=1;i<=n;i++)
        cin>>v[i]>>c[i]>>s[i];
    for (int i=1;i<=n;i++)
    {
        int k=1;
        for (k=1;k*2<s[i];k=k*2)
        {
            for (int j=m;j>=c[i]*k;j--)
                dp[j]=max(dp[j],dp[j-c[i]*k]+v[i]*k);
        }
        k--;
        k=s[i]-k;
        if (k!=0)
        {
            for (int j=m;j>=c[i]*k;j--)
                dp[j]=max(dp[j],dp[j-c[i]*k]+v[i]*k);
        }
    }
    cout<<dp[m];
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/asanagiyantia/p/11830781.html