• POJ3260 完全背包 + 多重背包 xingxing在努力


      这道题的意思是一个人有一定数额的银币若干个, 想用这些硬币买一些东西, 售货员会找零,现在问你如何用最少的银币买到东西。。。 先用完全背包预处理找零j块钱的时候最少需要多少硬币,然后用多重背包处理付款j块钱的时候最少需要多少银币, 最后将两个加起来就行。注意数组开大点。代码如下:

      

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int inf = 0x3f3f3f3f;
    int N, T;
    int V[100 + 10];   //硬币的面额
    int C[100 + 10];   //硬币的数量
    int back[30000 + 10];              //找零为j是需要的最少的银币的数量
    int f[30000 + 10];                 //付款为j时所需要的最少的银币数量
    
    void ComplatePack(int cost, int weight)
    {
        for(int j=cost; j<=30000; j++)
            if(f[j]>f[j-cost]+weight && f[j-cost]!=inf)
                f[j] = f[j-cost] + weight;
        return ;
    }
    
    void ZeroOnePack(int cost, int weight)
    {
        for(int j=30000; j>=cost; j--)
            if(f[j]>f[j-cost]+weight && f[j-cost]!=inf)
                f[j] = f[j-cost] + weight;
        return ;
    }
    
    void MultiPack(int cost ,int weight, int number)
    {
        if(cost*number>30000)
        {
            ComplatePack(cost, weight);
            return ;
        }
        int k = 1;
        while(k < number)
        {
            ZeroOnePack(k*cost, k*weight);
            number -= k;
            k *= 2;
        }
        ZeroOnePack(number*cost, number*weight);
    }
    
    int main()
    {
        while(scanf("%d%d", &N, &T) == 2)
        {
            for(int i=0; i<N; i++)
                scanf("%d", &V[i]);
            for(int i=0; i<N; i++)
                scanf("%d", &C[i]);
            memset(back, 0x3f, sizeof(back));
            back[0] = 0;
            for(int i=0; i<N; i++)            //预处理找零为j时所需银币最少
                for(int j=V[i]; j<=30000; j++)
                    if(back[j]>back[j-V[i]]+1 && back[j-V[i]]!=inf)
                        back[j] = back[j-V[i]] + 1;
            memset(f, 0x3f, sizeof(f));
            f[0] = 0;
            for(int i=0; i<N; i++)
                MultiPack(V[i], 1, C[i]);
            int res = inf;
            for(int i=T; i<=30000; i++)
            {
                if(back[i-T]!=inf&&f[i]!=inf&&back[i-T]+f[i]<res)
                    res = back[i-T] + f[i];
            }
            if(res == inf)
                printf("-1
    ");
            else 
                printf("%d
    ", res);
        }
        return 0;
    }
  • 相关阅读:
    hdu1879 继续畅通工程
    hdu1875 畅通工程再续 最小生成树并查集解决---kruskal
    hdu1863 畅通工程2 还是用并查集思想解决最小生成树问题
    hud2544dijkstra+堆优化
    PHP holiday1
    记忆化搜索hdu1078 dfs
    hdu 1548 楼梯 bfs或最短路 dijkstra
    隐藏原生html5 video controls
    工具网站gallery
    判断节点包含
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5012750.html
Copyright © 2020-2023  润新知