zoukankan      html  css  js  c++  java
  • hdu 2844 多重背包的转化问题 以及这个dp状态的确定

    在杭电上测试了下 这里的状态转移方程有两个。,。

    现在有价值val[1],val[2],…val[n]的n种硬币, 它们的数量分别为num[i]个. 然后给你一个m, 问你区间[1,m]内的所有数目, 由之前n种硬币来构造(即选取某些硬币使得这些硬币的价值和等于[1,m]区间的特定数), 最多能构造出这m个数中的多少个?

    初始化: dp为全0,且 dp[0][0]==1.

           对于每种硬币, 我们有两种可能的方式处理://重点 多重包的两种转化

           1.   Val[i]*num[i]>= m时, 对当前硬币做一次完全背包即可

           2.   Val[i]*num[i]<m时, 我们把当前硬币分成下面k+1类:

    然后 这里要引入一个多重背包转化为01包的二进制转化法

    上图。

    对于任意的十进制数 都可以转化为对应的二进制数  在背包问题中使用这个转化 可以有效的减少遍历的次数

    然后得说说这道题目的状态转移方程了 dp[j]表示前i个硬币的组合能否构成j这个数 这里得注意 题目问的是1到m能构成的次数 也就是说 dp过程结束以后 还得再遍历一遍 统计最后的结果

    #include<cstdio>
    #include<iostream>
    #include<string.h>
    using namespace std;
    int dp[100001];
    int val[101],num[101];
    int n,m;
    void compel_pack(int cost)//单层完全包
    {
        for(int i=cost;i<=m;i++) dp[i]=max(dp[i],dp[i-cost]);
    }
    void one_pack(int cost)//一次01包
    {
        for(int i=m;i>=cost;i--) dp[i]=max(dp[i],dp[i-cost]);
    }
    void multi_pack(int val,int num)
    {
        if(val*num>m) compel_pack(val);
        else
        {
            int k=1;
            while(k<num)//多重背包的01转化 二进制转换 将多重包拆解为多个01包
            {
                one_pack(k*val);
                num-=k;
                k*=2;
            }
            if(num>0) one_pack(num*val);
        } 
    }
    int main()
    {
        while(cin>>n>>m)
        {
            if(n==0&&m==0) break;
            for(int i=1;i<=n;i++) cin>>val[i];
            for(int i=1;i<=n;i++) cin>>num[i];
            memset(dp,0,sizeof(dp));
            dp[0]=1;
            for(int i=1;i<=n;i++)
            {
                multi_pack(val[i],num[i]);
            }
            int ans=0;
            for(int i=1;i<=m;i++)
            {
                if(dp[i]) ans++;
            }
            cout<<ans<<endl;
        }
        return 0;
    } 
  • 相关阅读:
    【原创】μC/OS Ⅱ工程中MAKETEST.BAT文件的改进与优化
    网络号和主机号等的分析和计算
    QQ电脑管家加速升级版便携版
    ARM发展历史
    μC/OS Ⅱ之任务就绪表的操作_2012.5.31
    删除word中的多余空行
    μC/OS II安装调试指南(带图解说明)
    WPF简单的User Control
    How to Databind SelectedItems of the ListPicker and RecurringDaysPicker
    数组排序
  • 原文地址:https://www.cnblogs.com/z1141000271/p/5764139.html
Copyright © 2011-2022 走看看