zoukankan      html  css  js  c++  java
  • 完全背包和多重背包的混合 F

    http://poj.org/problem?id=3260

     

    这个题目有点小难,我开始没什么头绪,感觉很乱。

    后来看了题解,感觉豁然开朗。

    题目大意:就是这个人去买东西,东西的价格是T,这个人拥有的纸币和数量。让你求这个人买东西的纸币量加上老板找给他的纸币量最少是多少。

    这个老板用于这个人拥有的纸币种类,数量是无限。

     

    思路:

    思路就是这个人看成多重背包,老板看成完全背包,f1[i] 表示这个人花了 i 的钱用的最少的纸币。f2[i] 表示老板凑出 i 的钱用的最少的纸币。

     

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 2e5 + 10;
    int N, V;
    int weight[maxn], num[maxn];
    int f1[maxn], f2[maxn], V1;
    void zeroonepack(int weight, int val, int f[]) {
        for (int i = V; i >= weight; i--) {
            f[i] = min(f[i], f[i - weight] + val);
        }
    }
    
    void completepack(int weight, int val, int f[]) {
        for (int i = weight; i <= V; i++) {
            f[i] = min(f[i], f[i - weight] + val);
        }
    }
    
    void multiplepack(int weight, int val, int count, int f[]) {
        if (count*weight >= V) completepack(weight, val, f);
        else {
            int t = 1;
            while (t < count) {
                zeroonepack(weight*t, val*t, f);
                count -= t;
                t *= 2;
            }
            zeroonepack(count*weight, count*val, f);
        }
    }
    
    int main() {
        while (scanf("%d%d", &N, &V1) != EOF) {
            int max_val = 0;
            for (int i = 1; i <= N; i++) {
                scanf("%d", &weight[i]);
                max_val = max(max_val, weight[i]);
            }
            for (int i = 1; i <= N; i++) scanf("%d", &num[i]);
            V = max_val * max_val + V1 + 10;
            memset(f1, inf, sizeof(f1));
            memset(f2, inf, sizeof(f2));
            f1[0] = 0, f2[0] = 0;
            for (int i = 1; i <= N; i++) {
                multiplepack(weight[i], 1, num[i], f1);//顾客
            }
            for (int i = 1; i <= N; i++) {
                completepack(weight[i], 1, f2);
            }
            //printf("v=%d v1=%d
    ", V, V1);
            int ans = inf;
            for (int i = 0; i <= V - V1; i++) {
                if (f1[V1 + i] != inf && f2[i] != inf) {
                    ans = min(f1[V1 + i] + f2[i], ans);
                }
            }
            if (ans != inf) printf("%d
    ", ans);
            else printf("-1
    ");
        }
        return 0;
    }

     

  • 相关阅读:
    swoole入门abc
    PHP实现定时任务(非linux-shell方式,与操作系统无关)
    PHP经典算法题
    lumen使用CORS解决跨域问题
    轻松搞定 JS 的this、call和apply
    Nginx与PHP工作原理
    PHP的cURL扩展库使用详解
    PHP 中的 cURL 爬虫实战基础
    jvm误区--动态对象年龄判定
    从源码分析如何优雅的使用 Kafka 生产者
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/10925113.html
Copyright © 2011-2022 走看看