LuoguP1858 多人背包(DP)

第\(K\)优解这类问题可在\(DP\)过程中通过添维解决。归并出当前前\(K\)大的解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define QWQ
#ifdef QWQ
#define D_e_Line printf("\n---------------\n")
#define D_e(x) cout << (#x) << " : " << x << "\n"
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define TIME() fprintf(stderr, "\nTIME : %.3lfms\n", clock() * 1000.0 / CLOCKS_PER_SEC)
#else
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
#endif
struct ios {
    template<typename ATP> inline ios& operator >> (ATP &x) {
        x = 0; int f = 1; char c;
        for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
        while(c >= '0' && c <='9') x = x * 10 + (c ^ '0'), c = getchar();
        x *= f;
        return *this;
    }
}io;
using namespace std;
template<typename ATP> inline ATP Max(ATP a, ATP b) {
    return a > b ? a : b;
}
template<typename ATP> inline ATP Min(ATP a, ATP b) {
    return a < b ? a : b;
}
template<typename ATP> inline ATP Abs(ATP a) {
    return a < 0 ? -a : a;
}

const int N = 207;

long long f[5007][51], tmp[5007];

struct nod {
    long long cost, val;
} a[N];
int main() {
    int n, K, V;
    io >> K >> V >> n;
    R(i,1,n){
        io >> a[i].cost >> a[i].val;
    }

    Fill(f, 0xcf);
    f[0][1] = 0;

    R(i,1,n){
        nR(j,V,a[i].cost){
            int tot1 = 1, tot2 = 1, tot3 = 0;
            while(tot3 <= K){
                if(f[j][tot1] > f[j - a[i].cost][tot2] + a[i].val){
                    tmp[++tot3] = f[j][tot1++];
                }
                else{
                    tmp[++tot3] = f[j - a[i].cost][tot2++] + a[i].val;
                }
            }
            R(k,1,K) f[j][k] = tmp[k];
        }
    }

    long long ans = 0;
    R(i,1,K){
        ans += f[V][i];
    }

    printf("%lld", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/bingoyes/p/11748282.html

时间: 2024-10-10 05:04:36

LuoguP1858 多人背包(DP)的相关文章

hdu--1059--多重背包||DP||搜索

碎碎念----- 突然 觉得好无聊~~ 还好 只有4天了~~ 直接上题吧~~ touch  me 使用多重背包的代码是转自---键盘上的舞者---- 写得特别有想法 使用dp的代码是porker写的.. 使用搜索的 我一开始是将价值从低到高搜索的 这样TLE了,,因为速度实在是太慢了 假如有arr[k]个 那么我要有arr[k]+1个操作... 但是 按价值从高到低的搜索 只要遵循 尽量在不到sum/2的时候去搜就是了 有就添加进来...但这个方法的正确性 没有得到证明... 1 #includ

[XJOI]noip43 T2多人背包

多人背包 DD 和好朋友们要去爬山啦!他们一共有 K 个人,每个人都会背一个包.这些包的容量是相同的,都是 V.可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值.在 DD 看来,合理的背包安排方案是这样的:1. 每个人背包里装的物品的总体积恰等于包的容量. 2. 每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品. 3. 任意两个人,他们包里的物品清单不能完全相同. 在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢? 输入格式: 第一行有三个整数:K

P1858 多人背包

P1858 多人背包 题目描述 求01背包前k优解的价值和 要求装满 调试日志: 初始化没有赋给 dp[0] Solution 首先补充个知识点啊, 要求装满的背包需要初始赋 \(-inf\), 边界为 \(dp[0] = 0\) 第 \(k\) 优解的01背包 以 \(dp[j][k]\) 表示 容量为 \(j\) 的背包的第 \(k\) 优解 用到了归并排序的思想 对于第 \(i\) 个物品, 容量为 \(j\), 我们有两种选择: 选第 \(i\) 个物品 不选第 \(i\) 个物品 对于

UVA - 10817 Headmaster&#39;s Headache (状压类背包dp+三进制编码)

题目链接 题目大意:有S门课程,N名在职教师和M名求职者,每名在职教师或求职者都有自己能教的课程集合以及工资,要求花费尽量少的钱选择一些人,使得每门课程都有至少两人教.在职教师必须选. 可以把“每个课程已经分别有几个人教”作为状态来进行转移,每个人能教的课程集合作为“物品重量”,工资作为“价值”来更新dp值,类似01背包,每放进一个人,从后往前更新即可. 状态的表示可以用三进制编码,为了写起来舒服,我写了个结构体作为状态和编码转换的桥梁,也可以进行状态的“加法运算”,虽然速度比较慢就是了~~ 有

[BZOJ 1025] 游戏 置换群 背包DP

题意 对于一个 $n$ 阶置换群 $A$ , 它的循环节大小分别为 $a_1, a_2, ..., a_m$ , 则有 $\sum_{i = 1} ^ m a_i = n$ . 定义 $f(A)$ 为它的所有循环节的最小公倍数, 即 $f(A) = [a_1, a_2, ..., a_m]$ . 求在所有 $n$ 阶置换群中, $f(A)$ 有多少种取值. $n \le 1000$ . 分析 判断 $K$ 可不可取. $K = \prod_{i = 1} ^ r {s_r} ^ {t_r}$ 可

hdu 5234 Happy birthday 背包 dp

Happy birthday Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5234 Description 今天是Gorwin的生日.所以她的妈妈要实现她的一个愿望.Gorwin说她想吃很多蛋糕.所以他妈妈带她来到了蛋糕园. 这个园子被分成了n*m个方格子.在每一个格子里面,有一个蛋糕.第i行,第j列的格子中有一个重量为wij千克的蛋糕,Gorwin从左上角(1,1

hdu 1171 Big Event in HDU(背包DP)

题意: 杭电搬迁,有N种设备,每种设备有个价值V,数量M,要求将这些设备平分,使得平分后两边的总价值尽可能地相等. 输出两边各自的总价值. 思路: 背包DP后,P=所有的总价值/2,然后从P开始往两边找到第一个满足的价值. 可以降维,但是要注意for循环的顺序. 看代码. 代码: int v[55], m[55]; bool dp[250005]; int main(){ int n; while(scanf("%d",&n)!=EOF && n>=0){

POJ 1384 Piggy-Bank 背包DP

所谓的完全背包,就是说物品没有限制数量的. 怎么起个这么intimidating(吓人)的名字? 其实和一般01背包没多少区别,不过数量可以无穷大,那么就可以利用一个物品累加到总容量结尾就可以了. 本题要求装满的,故此增加个限制就可以了. #include <stdio.h> #include <stdlib.h> #include <string.h> inline int min(int a, int b) { return a < b? a : b; } c

BZOJ 1042 硬币购物(完全背包+DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1042 题意:给出四种面值的硬币c1,c2,c3,c4.n个询问.每次询问用d1.d2.d3.d4个相应的硬币能够拼出多少种总和为s? 思路:(1)首先,用完全背包求出f[i]表示四种硬币的数量无限制拼出i的方案数. (2)接着我们来理解 x=f[s]-f[s-(d1+1)*c1]的含义:x表示c1硬币的数量不超过d1个而其他三种硬币的数量不限制拼成s的方案数.我们举着例子来说明, 假设