zoukankan      html  css  js  c++  java
  • B. Shaass and Bookshelf DP

    http://codeforces.com/contest/294/problem/B

    据说是贪心,我用了一个复杂度是2e8的dp水过去了。

    其实这题就是给你n个数,每个数有两个权值,分成两组,使得第一个权值之和,和第二个权值之和的最大值最小。

    那么直接设dp[i][j][k][h]表示前i个数中,选了j个,第一个权值的和是k,第二个权值是h,是否可能。

    这里是一定要选出n个的,就是n个数都必须使用,才能滚动数组。(把第二维滚动)

    如果是从n个数中选出k个,那么就不能滚动了。

    那么第一维是01背包直接省略,j那里可以滚动数组。

    总复杂度2e8

    然后题解是贪心......

    还有要注意,k要大于h,就是底下的书要长于上面的书。

    #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>
    struct node {
        int ti, wi;
    }a[111];
    int dp[2][200 + 2][10000 + 2];
    void work() {
        int n;
        cin >> n;
        int DFN = 1;
        int sumti = 0, sumwi = 0;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i].ti >> a[i].wi;
            sumti += a[i].ti;
            sumwi += a[i].wi;
        }
        if (n == 1) {
            cout << min(a[1].ti, a[1].wi) << endl;
            return;
        }
    //    sort(a + 1, a + 1 + n);
        dp[0][0][0] = DFN;
        int now = 0;
        for (int i = 1; i <= n; ++i) {
            now = !now;
            ++DFN;
            for (int j = sumti; j >= 0; --j) {
                for (int k = sumwi; k >= 0; --k) {
                    if (j >= a[i].ti && dp[!now][j - a[i].ti][k] == DFN - 1) {
                        dp[now][j][k] = DFN;
                    }
                    if (k >= a[i].wi && dp[!now][j][k - a[i].wi] == DFN - 1) {
                        dp[now][j][k] = DFN;
                    }
                }
            }
        }
        int ans = inf;
        for (int i = 0; i <= sumti; ++i) {
            for (int j = 0; j <= i; ++j) {
                if (dp[now][i][j] == DFN) {
                    ans = min(ans, max(i, j));
                }
            }
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    斯坦福机器学习视频之线性回归习题详解
    linuxc程序设计之passwd与shadow解析(转)
    DeepLearning之MLP解析
    The Linux Environment之getopt_long()
    插入排序
    堆排序
    归并排序
    快速排序
    CyclicBarrier与CountDownLatch的区别
    判断是否是平衡二叉树(左子树与右子树高度不大于1)
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6238454.html
Copyright © 2011-2022 走看看