zoukankan      html  css  js  c++  java
  • HDU2191 悼念512汶川大地震遇难同胞(多重背包)

    题目链接

    分析:

    一直在看多重背包,一开始做了几个,几乎全部TLE。原来是要用二进制优化,学习了一下(详情见本博客)。

    第一种做法:

    View Code
    #include <stdio.h>
    #include <string.h>
    
    #define MAXN 3000
    
    int n, m;
    
    int value[MAXN], weight[MAXN];
    int dp[150];
    
    int max(int x, int y){
        return x > y ? x : y;
    }
    
    int main(){
        int T, p, h, c, cnt, i, j;
        scanf("%d", &T);
        while(T--){
            memset(dp, 0, sizeof(dp));
            scanf("%d %d", &n, &m);
            cnt = 0;
            while(m--){
                scanf("%d %d %d", &p, &h, &c);
                for(i=1; i<=c; i<<=1){
                    value[cnt] = p*i;
                    weight[cnt++] = h*i;
                    c -= i;
                }
    
                if(c > 0){
                    value[cnt] = p*c;
                    weight[cnt++] = h*c;
                }
            }
            for(i=0; i<cnt; i++){
                for(j=n; j>=value[i]; j--){
                    dp[j] = max(dp[j], dp[j-value[i]]+weight[i]);
                }
            }
            printf("%d\n", dp[n]);
        }
    
        return 0;
    }

    第二种做法:

    0/1背包和完全背包结合。

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int dp[120];
    
    int main(){
        int T, n, m, p, w, c, i, k;
    
        scanf("%d", &T);
        while(T--){
            memset(dp, 0, sizeof(dp));
            scanf("%d %d", &n, &m);
            while(m--){
                scanf("%d %d %d", &p, &w, &c);
                if(p*c >= n){
                    for(i=p; i<=n; i++){
                        if(dp[i] < dp[i-p]+w) dp[i] = dp[i-p]+w;
                    }
                }
                else{
                    k = 1;
                    while(c){
                        if(k > c) k = c;
                        c -= k;
                        for(i=n; i>=k*p; i--){
                            if(dp[i] < dp[i-k*p]+k*w) dp[i] = dp[i-k*p]+k*w;
                        }
                        k <<= 1;
                    }
                }
            }
            printf("%d\n", dp[n]);
        }
        return 0;
    }

    后来用了下贪心,没对。查了下,说的有理。

  • 相关阅读:
    数字和字母交替打印
    日期和字符串的转化
    redis简介
    管理MySQL的命令
    创建mysql数据表成功
    微信账号 echo_server 的实现
    html5 画个圈
    php练习1
    人生十大点
    养生“六伤”、“十二莫”、“十二少”
  • 原文地址:https://www.cnblogs.com/tanhehe/p/2998837.html
Copyright © 2011-2022 走看看