程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 2844 Coins(多重背包)

HDU 2844 Coins(多重背包)

編輯:C++入門知識

HDU 2844 Coins(多重背包)


 

現在有價值val[1],val[2],…val[n]的n種硬幣, 它們的數量分別為num[i]個. 然後給你一個m, 問你區間[1,m]內的所有數目, 由之前n種硬幣來構造(即選取某些硬幣使得這些硬幣的價值和等於[1,m]區間的特定數), 最多能構造出這m個數中的多少個?

分析:

基本的完全背包問題.

我們令dp[i][j]==x表示用前i種硬幣且硬幣總價值總價值正好等於j時, 有多少種方法.

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

對於每種硬幣, 我們有兩種可能的方式處理:

1. Val[i]*num[i]>= m時, 對當前硬幣做一次完全背包即可.

2. Val[i]*num[i]

1個 2個 4個… 2^(k-1)個, 以及 num[i]-2^k+1個

然後我們對上面k+1類物品每個都做一次01背包即可, 因為對上面k+1類新物品的01選擇會覆蓋我們所有可能的對原來第i類物品做的任何選擇.

最終所求: 所有使得dp[n][j]!=0 的j值得和. (1<=j<=m)

AC代碼:

 

#include
#include
#include
using namespace std;
const int maxn=100000+5;

int n;//物品種數
int m;//總金錢數
int cost[100+5];//第i種物品的花費
int num[100+5]; //第i種物品的數量
int dp[maxn];

//1次01背包過程
void ZERO_ONE_PACK(int cost)
{
    for(int i=m;i>=cost;i--)
        dp[i] += dp[i-cost];
}

//1次完全背包過程
void COMPLETE_PACK(int cost)
{
    for(int i=cost;i<=m;i++)
        dp[i] += dp[i-cost];
}

//1次多重背包過程
void MULTIPLY_PACK(int cost,int num)
{
    if(cost*num>=m)
    {
        COMPLETE_PACK(cost);
        return ;
    }

    int k=1;
    while(k

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved