zoukankan      html  css  js  c++  java
  • poj 3260 The Fewest Coins 多重背包+完全背包

    题目链接:http://poj.org/problem?id=3260

    给店家的钱是多重背包 dp[]

    店家的找钱是完全背包 dp2[]

    然后最后 其中i表示多给了多少钱 也就是需要找回多少钱 

    int ans = INF;

    ans = min(ans, dp[m+i] + dp2[i]);

    是一个比较简单的思路

    神坑题 

    看到每种货币的面值不大于120 我就觉得找钱一定不会超过119块钱结果wa到死

    后来才发现不是的啊

    之所以我有这种思维定式是因为现实生活中有1块钱这种货币单位

    考虑一种极限的情况

    只有面值为120元、119元两种货币

    然后你只有120那种 要去买价值为120*82 + 119 = 9959元的东西

    那119的部分需要你给店家119张120块钱让他找你119张119块钱Orz 【三观啊...

    这样一来可以大概估计找钱的一个上界是14400

    所以两个DP过程的容量都加上14400然后再去做就能过T^T

    另外写CompletePack2()的时候我明明没有改V的值可是V的值变了

    后来才反应过来这种事情很可能就是数组越界

    检查了一下果然边界情况没有控制好

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <set>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    typedef long long ll;
    
    const int maxn = 110;
    const int maxm = 10200;
    const int INF = 100000;
    
    int a[maxn], c[maxn];
    int dp[maxm + 15000];
    int dp2[15000];
    int V;
    
    void ZeroOnePack(int cost, int weight)
    {
        for(int i = V; i >= cost; i--)
        {
            dp[i] = min(dp[i], dp[i-cost] + weight);
        }
    }
    
    void CompletePack(int cost, int weight)
    {
        for(int i = cost; i <= V; i++)
        {
            dp[i] = min(dp[i], dp[i-cost] + weight);
        }
    }
    
    void MultiplePack(int cost, int weight, int amount)
    {
        if(cost*amount >= V)
        {
            CompletePack(cost, weight);
            return;
        }
        int k = 1;
        while(k < amount)
        {
            ZeroOnePack(k*cost, k*weight);
            amount = amount - k;
            k *= 2;
        }
        ZeroOnePack(amount*cost, amount*weight);
    }
    
    void CompletePack2(int cost, int weight)
    {
        for(int i = cost; i < V; i++)
        {
            dp2[i] = min(dp2[i], dp2[i-cost] + weight);
        }
    }
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
    
        int n, m;
    
        while(scanf("%d%d", &n, &m) == 2)
        {
            memset(dp, 0x3f, sizeof(dp));
            memset(dp2, 0x3f, sizeof(dp2));
            dp[0] = dp2[0] = 0;
    
            for(int i = 0; i < n; i++)
                scanf("%d", &a[i]);
    
            for(int i = 0; i < n; i++)
                scanf("%d", &c[i]);
    
            V = m + 14400;
            for(int i = 0; i < n; i++)
                MultiplePack(a[i], 1, c[i]);
    
            V = 14400;
            for(int i = 0; i < n; i++)
            {
                CompletePack2(a[i], 1);
            }
    
            int ans = INF;
            for(int i = 0; i < 14400; i++)
            {
                ans = min(ans, dp[m+i] + dp2[i]);
            }
    
            if(ans == INF)
                printf("-1
    ");
            else
                printf("%d
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    Linux 禁用ipv6
    【搬运】Get Log Output in JSON,通过Log4j2与Logback输出JSON格式日志
    Gnome禁用tracker-miner-apps、tracker-miner-fs、tracker-store
    Sentry错误日志监控你会用了吗?
    django执行源生的mysql语句
    django实现自定义manage命令的扩展
    C++教程详解
    python数据分析教程大全
    将mysql主键id从1开始 变为自增
    django restful framework教程大全
  • 原文地址:https://www.cnblogs.com/dishu/p/4296065.html
Copyright © 2011-2022 走看看