zoukankan      html  css  js  c++  java
  • hdu 5445 Food Problem (多重背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5445

    题解:一看就像多重背包就是怎么看都不好做。但是这里有点明显的就是有两个背包,一个是糖果一个是箱子,于是不妨就试试两个多重背包,先考虑用这些糖果能否满足条件设dp[i]表示构成能量为i的糖果最小需要多少体积,然后将所需要的体积保存下来那么只要找到一些箱子总共能容纳的体积大于等于这个值就行这时的dp[i]又表示容积总共是i的箱子最少需要多少钱。其实这样也是不够严谨的因为这样也不能保证糖果刚好能放好但是理论上是可行的。还有要注意的就是多重背包要注意二进制的优化。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define inf 0X3f3f3f3f
    using namespace std;
    const int M = 2e5 + 10;
    const int Max = 50000 + 10;
    int dp[M];
    int t[M] , u[M] , v[M];
    int x[M] , y[M] , z[M];
    int main() {
        int test , n , m , q;
        scanf("%d" , &test);
        while(test--) {
            int ans = inf;
            scanf("%d%d%d" , &n , &m , &q);
            for(int i = 0 ; i < n ; i++) {
                scanf("%d%d%d" , &t[i] , &u[i] , &v[i]);
            }
            for(int i = 0 ; i < m ; i++) {
                scanf("%d%d%d" , &x[i] , &y[i] , &z[i]);
            }
            memset(dp , inf , sizeof(dp));
            dp[0] = 0;
            for(int i = 0 ; i < n ; i++) {
                int mm = v[i];
                for(int j = 1 ; mm > 0 ; j <<= 1) {
                    int gg = min(j , mm);
                    for(int l = Max ; l >= gg * t[i] ; l--) {
                        dp[l] = min(dp[l] , dp[l - gg * t[i]] + gg * u[i]);
                    }
                    mm -= j;
                }
            }
            for(int i = q ; i <= Max ; i++) {
                if(dp[i] != inf) {
                    ans = min(ans , dp[i]);
                }
            }
            memset(dp , 0 , sizeof(dp));
            for(int i = 0 ; i < m ; i++) {
                int mm = z[i];
                for(int j = 1 ; mm > 0 ; j <<= 1) {
                    int gg = min(j , mm);
                    for(int l = Max ; l >= gg * y[i] ; l--) {
                        dp[l] = max(dp[l] , dp[l - gg * y[i]] + gg * x[i]);
                    }
                    mm -= j;
                }
            }
            int flag = 0;
            for(int i = 1 ; i <= Max - 10 ; i++) {
                if(dp[i] >= ans && ans != inf) {
                    flag = i;
                    break;
                }
            }
            if(flag) printf("%d
    " , flag);
            else printf("TAT
    ");
        }
        return 0;
    }
  • 相关阅读:
    经典的阿里前端笔试题
    Javascript之浏览器兼容EventUtil
    Javascript之对象的创建
    奇妙的CSS之CSS3新特性总结
    前端优化之无阻塞加载脚本
    正则表达式规则与常见的正则表达式
    全端工程师
    最全前端面试问题及答案总结--《转载》
    奇妙的CSS之布局与定位
    关于在django框架里取已登录用户名字的问题
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7652597.html
Copyright © 2011-2022 走看看