码迷,mamicode.com
首页 > 其他好文 > 详细

P1858 多人背包

时间:2018-10-26 22:20:31      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:name   lin   def   str   i++   mat   getchar   efi   flag   

P1858 多人背包

题目描述
求01背包前k优解的价值和
要求装满


调试日志: 初始化没有赋给 dp[0]


Solution

首先补充个知识点啊, 要求装满的背包需要初始赋 \(-inf\), 边界为 \(dp[0] = 0\)
\(k\) 优解的01背包
\(dp[j][k]\) 表示 容量为 \(j\) 的背包的第 \(k\) 优解
用到了归并排序的思想
对于第 \(i\) 个物品, 容量为 \(j\), 我们有两种选择:

  1. 选第 \(i\) 个物品
  2. 不选第 \(i\) 个物品

对于 \(1-k\) 中的每一个解做抉择, 我们可以得到 \(2k\) 种答案
由于答案分两边(选或不选)内部有序, 归并得到前 \(k\) 优即可
复杂度 \(O(nmk)\)

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#define LL long long
#define REP(i, x, y) for(int i = (x);i <= (y);i++)
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 10019;
int K, V, num;
int w[maxn], v[maxn];
int temp[maxn];
int dp[maxn][119];
int main(){
    K = RD(), V = RD(), num = RD();
    REP(i, 1, num)w[i] = RD(), v[i] = RD();
    REP(i, 0, V)REP(k, 1, K)dp[i][k] = -1e9;
    dp[0][1] = 0;
    REP(i, 1, num){
        for(int j = V;j >= w[i];j--){
            int p1 = 1, p2 = 1, cnt = 0;
            while(cnt <= K){
                if(dp[j][p1] > dp[j - w[i]][p2] + v[i])temp[++cnt] = dp[j][p1++];
                else temp[++cnt] = dp[j - w[i]][p2++] + v[i];
                }
            REP(k, 1, K)dp[j][k] = temp[k];
            }
        }
    int ans = 0;
    REP(i, 1, K)ans += dp[V][i];
    printf("%d\n", ans);
    return 0;
    }

P1858 多人背包

标签:name   lin   def   str   i++   mat   getchar   efi   flag   

原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9858413.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!