zoukankan      html  css  js  c++  java
  • HDU 3591 多重背包

    给出N种钱币和M

    给出N种钱币的面值和个数

    NPC拿着这N些钱币去买价值M的物品,能够多付。然后被找零,找零的钱也为这些面值。但没有数量限制

    问最少经手的钱币数量


    对于NPC做一个付款多重背包

    然后对于找零做一个全然背包

     ans=Min(dp1[i]+dp2[i-m],ans);


    #include "stdio.h"
    #include "string.h"
    
    
    int n,m;
    int dp1[20010],dp2[20010],c[20010],v[20010];
    void onezero_pack(int v,int k)
    {
        int i;
        for (i=20000;i>=v;i--)
            if (dp1[i-v]!=-1 && (dp1[i-v]+k<dp1[i] || dp1[i]==-1) )
            dp1[i]=dp1[i-v]+k;
    }
    
    void complete_pack(int v)
    {
        int i;
        for (i=v;i<=20000;i++)
            if (dp1[i-v]!=-1 && (dp1[i-v]+1<dp1[i] || dp1[i]==-1) )
            dp1[i]=dp1[i-v]+1;
    }
    
    void multiple_pack(int v,int c)
    {
        int k;
        if (v*c>=20000)
            complete_pack(v);
        else
        {
            k=1;
            while (k<c)
            {
                onezero_pack(k*v,k);
                c-=k;
                k*=2;
            }
            if (c>0) onezero_pack(c*v,k);
        }
    }
    
    int Min(int a,int b)
    {
        if (a<b) return a;
        else return b;
    }
    int main()
    {
        int Case,i,j,ans;
        Case=0;
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            if (n+m==0) break;
            for (i=1;i<=n;i++)
                scanf("%d",&v[i]);
            for (i=1;i<=n;i++)
                scanf("%d",&c[i]);
    
            memset(dp1,-1,sizeof(dp1));
            dp1[0]=0;
    
    
            for (i=1;i<=n;i++)
                multiple_pack(v[i],c[i]);
    
           memset(dp2,-1,sizeof(dp2));
            dp2[0]=0;
            for (i=1;i<=n;i++)
                for (j=0;j<=20000-v[i];j++)
                {
                    if (dp2[j]!=-1 && (dp2[j]+1<dp2[j+v[i]] || dp2[j+v[i]]==-1) )
                        dp2[j+v[i]]=dp2[j]+1;
                }
    
            ans=0x3f3f3f3f;
            for (i=m;i<=20000;i++)
                if (dp1[i]!=-1 && dp2[i-m]!=-1)
                    ans=Min(dp1[i]+dp2[i-m],ans);
    
            printf("Case %d: ",++Case);
            if (ans==0x3f3f3f3f)
                printf("-1
    ");
            else
                printf("%d
    ",ans);
        }
        return 0;
    }
    



  • 相关阅读:
    转 将python的datetime转换为unix时间戳
    VMware 虚拟机中添加新硬盘的方法
    UBUNTU 安装 nodejs
    ubuntu 20 查看site-package 目录
    基于C++代码的UE4学习(四)—— 定时器
    ObjectMapper 动态用法
    关于Mybatis中Mapper是使用XML还是注解的一些思考
    Spring Boot 中使用 Jedis 及 Lettuce的对比
    批量切换版本
    Build OpenJdk
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6747613.html
Copyright © 2011-2022 走看看