首页 > 其他分享 >HDU-2639 Bone Collector ||

HDU-2639 Bone Collector ||

时间:2022-12-23 14:11:47浏览次数:47  
标签:HDU 2639 int 35 价值 Collector

HDU-2639 Bone Collector ||

01背包问题,但是需要输出的是可以获得的第 \(k\) 大价值。

思路

状态定义?

我们要求的是第 \(k\) 大价值,所以当我们得到一个当前第 \(k + 1\) 大的价值的时候,可以直接舍去,因为它一定不是第 \(k\) 大的价值。然后我们又需要知道目前得到的 \(k\) 个价值具体是多少,所以我们在原来 \(01\) 背包的基础上在加一维。

所以我们定义 \(f[i][j][k]\) : 遍历到第 \(i\) 个物品,且体积不超过 \(j\) 时可得的第 \(k\) 大价值是多少?

为了方便,滚动数组优化掉第一个维度,即状态变成 \(f[i][j]\) :体积不超过 \(j\) 时可得的第 \(j\) 大价值是多少。

回想一下 \(01\) 背包的状态转移方程 \(f[i][j] = max(f[i - 1][j],f[i - 1][j - v[i]] + w[i])\)

划分了当前物品选和不选。显然这里的选择会影响到当前状态的 \(k\) 个最大值。

所以我们取出这两种选法对应的 \(2 *k\) 个数,排序成新的 \(k\) 个最大数。

实现:

#include <stdio.h>
#include <algorithm>
using namespace std;
int f[1005][35], wei[105], val[105];
int main()
{
    int _;
    scanf("%d", &_);
    while (_--)
    {
        int n, v, k;
        scanf("%d%d%d", &n, &v, &k);
        for (int i = 1; i <= n; i++)
            scanf("%d", &val[i]);
        for (int i = 1; i <= n; i++)
            scanf("%d", &wei[i]);

        for (int i = 1; i <= v; i++)
            for (int j = 1; j <= k; j++)
                f[i][j] = 0;

        for (int i = 1; i <= n; i++)
        {
            for (int j = v; j >= wei[i]; j--)
            {
                //a数组记录的是不选第 i 个物品的 k 个最大价值
                //b数组记录的是选第 i 个物品的 k 个最大价值
                int a[35] = {0}, b[35] = {0};
                for (int l = 1; l <= k; l++)
                {
                    a[l] = f[j][l];
                    b[l] = f[j - wei[i]][l] + val[i];
                }
                a[k + 1] = b[k + 1] = -1;

                int ai = 1, bi = 1;
                for (int l = 1; l <= k && (a[ai] != -1 || b[bi] != -1); l++)
                {
                    if (a[ai] > b[bi])
                        f[j][l] = a[ai++];
                    else
                        f[j][l] = b[bi++];
                    //相同的数算同一个
                    if (f[j][l] == f[j][l - 1])
                        l--;
                }
            }
        }
        printf("%d\n", f[v][k]);
    }
    return 0;
}

标签:HDU,2639,int,35,价值,Collector
From: https://www.cnblogs.com/zxr000/p/17000553.html

相关文章

  • HDU4553 线段树维护最长连续区间
    //题意:(略了)//思路:这里很明显是要维护区间最大连续子段,按照以下优先级查找//A1.左边区间的连续子段是否满足//A2.左右两个区间中间合并起来的子段是否满足......
  • HDU 2602 Bone collector
    HDU2602Bonecollector题意:已知\(N\)个糖果的重量和价值.我们有一个口袋,最多可以装\(V\)重量的糖果.问口袋最多能放多少价值的糖果进去?思路:01背包问题......
  • HDU-Red and Black
     ProblemDescriptionThereisarectangularroom,coveredwithsquaretiles.Eachtileiscoloredeitherredorblack.Amanisstandingonablacktile.Froma......
  • HDU5091 Beam Cannon
    \(HDU5091\)\(Beam\)\(Cannon\)一、题目大意有\(n\)个点(\(n<=10000\)),点的坐标绝对值不超过\(20000\),然后问你用一个\(w*h(1<=w,h<=40000)\)的矩形,矩形的边平行于坐标......
  • I Hate It HDU - 1754 - 线段树
    很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。这让很多学生很反感。不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,......
  • HDU 4614 ——线段树+二分
    //题意:茜茜学姐的情人节到了!众所周知,茜茜学姐喜欢帅气的学弟,所以她当然有很多学弟送的花瓶,据不完全统计,茜茜学姐有N个花瓶(标号为0~N-1)。当然茜茜学姐也是个魅力四射......
  • CVE-2022-2639【Linux Kernel openvswitch 模块权限提升】
    漏洞影响版本:3.13≤LinuxKernel<5.18Exp地址:https://github.com/avboy1337/CVE-2022-2639-PipeVersion查看内核版本:编译exploit.c执行exp进行提权:......
  • hdu:继续畅通工程(kruskal的MST并查集实现)
    ProblemDescription省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表......
  • hdu:小希的迷宫(并查集)
    ProblemDescription上次Gardon的迷宫城堡小希玩了很久,现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说......
  • HDU4801——思维,生成树(口糊)
    //题意:有坐标图上有N个点,每个点有一个收益,要求修n-1条路联通所有点。现在有一个免单机会,即免除一条路的花费,求max(免除花费的路的两端点的收益和/n-1条路的总花费)//思路:......