1. 程式人生 > >POJ 1742 Coins 【多重背包DP】

POJ 1742 Coins 【多重背包DP】

數量 printf can 硬幣 ring editable urn content std

題意:有n種面額的硬幣。面額、個數分別為A_i、C_i,求最多能搭配出幾種不超過m的金額?

思路:dp[j]就是總數為j的價值是否已經有了這種方法,如果現在沒有,那麽我們就一個個硬幣去嘗試直到有,這種價值方法有了的話,那麽就是總方法數加1。多重背包可行性問題

傳統多重背包三重循環會超時,因為只考慮是否可行,沒有考慮剩余面額數量的因素。

o(n*v)方法

#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <algorithm>
using namespace std;

int dp[100005]; //表示當前i價格是否出現過
int sum[100005];//當價格達到i時,最多使用這一種硬幣的次數
int v[105],c[105];

int main()
{
    int i,j,n,m;
    while(~scanf("%d%d",&n,&m),n+m)
    {
        for(i = 1;i<=n;i++)
            scanf("%d",&v[i]);
        for(i = 1;i<=n;i++)
            scanf("%d",&c[i]);
        memset(dp,0,sizeof(dp));
        dp[0] = 1;
        int ans = 0;
        for(i=1;i<=n;i++)
        {
            memset(sum,0,sizeof(sum));//關鍵是用sum來限定了次數
            for(j = v[i];j<=m;j++)//循環檢查看是否能夠出現前邊沒有出現的價格
            {
                if(!dp[j] && dp[j-v[i]] && sum[j-v[i]]<c[i])
				{ //如果j價格沒有出現過,且j-v[i]出現過,並且使用i硬幣的次數沒有超出給定的數量
                    dp[j] = 1;
                    sum[j] = sum[j-v[i]]+1;//使用次數+1
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    
    return 0;
}

POJ 1742 Coins 【多重背包DP】