zoukankan      html  css  js  c++  java
  • vijos P1412多人背包 DP的前k优解

    https://vijos.org/p/1412

    把dp设成,dp[i][v][k]表示在前i项中,拥有v这个背包,的第k大解是什么。

    那么dp[i][v][1...k]就是在dp[i - 1][v][1...k]和dp[i - 1][v - w[i]][1...k] + val[i]中合并得来。

    用O(k)的算法可以找出来,因为是有序的。

    注意同一个物品只能用一次。

    dp的初始化就有些不同。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 5000 + 20;
    int w[maxn], val[maxn];
    int dp[maxn][50 + 20];
    int k, tot, n;
    int a[maxn], b[maxn];
    vector<int>vc;
    void work() {
        scanf("%d%d%d", &k, &tot, &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d%d", &w[i], &val[i]);
        }
        memset(dp, -0x3f, sizeof dp);
        dp[0][1] = 0;
        for (int i = 1; i <= n; ++i) {
            for (int v = tot; v >= w[i]; --v) {
                int lena = 0, lenb = 0;
                for (int h = 1; h <= k; ++h) {
                    a[++lena] = dp[v][h];
                    b[++lenb] = dp[v - w[i]][h] + val[i];
                }
                int toa = 1, tob = 1;
                for (int h = 1; h <= k; ++h) {
                    if (a[toa] > b[tob] && toa <= lena) {
                        dp[v][h] = a[toa++];
                    } else {
                        dp[v][h] = b[tob++];
                    }
                }
            }
        }
    //    cout << dp[tot][1] << endl;
    //    cout << dp[tot][2] << endl;
        int ans = 0;
        for (int i = 1; i <= k; ++i) {
            ans += dp[tot][i];
        }
        ans = max(ans, 0);
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    【转载】大型系统中使用JMS优化技巧
    【原创】JMS发布者订阅者【异步接收消息】
    【原创】JMS生产者和消费者【PTP异步接收消息】
    泛型
    For-Each循环
    策略模式(Strategy)
    Sort--快速排序
    Serach
    Sort--冒泡排序
    数值交换
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6397905.html
Copyright © 2011-2022 走看看