NYOJ 995 硬幣找零(完全揹包)

硬幣找零


時間限制:1000 ms  |  內存限制:65535 KB





該題仔細思考下,就是一個完全揹包問題,因爲每種硬幣無限多,如果j>ocnis[i],有要和不要兩種可能,看哪種硬幣數量較少,如果j<coins[i] ,dp[j]就不用更新了,保留以前的值,如果dp【s】大於總錢數,說明總錢數不能被完全換零,那麼找到最大能被換零的錢。所以動態轉移方程爲dp[j] = min(dp[j],dp[j-coins[i]]+1);


描述
在現實生活中,我們經常遇到硬幣找零的問題,例如,在發工資時,財務人員就需要計算最少的找零硬幣數,以便他們能從銀行拿回最少的硬幣數,並保證能用這些硬幣發工資。
我們應該注意到,人民幣的硬幣系統是 100,50,20,10,5,2,1,0.5,0.2,0.1,0.05,
0.02,0.01 元,採用這些硬幣我們可以對任何一個工資數用貪心算法求出其最少硬幣數。 
但不幸的是: 我們可能沒有這樣一種好的硬幣系統, 因此用貪心算法不能求出最少的硬幣數,甚至有些金錢總數還不能用這些硬幣找零。例如,如果硬幣系統是 40,30,25 元,那麼 37元就不能用這些硬幣找零;95 元的最少找零硬幣數是 3。又如,硬幣系統是 10,7,5,1元,那麼 12 元用貪心法得到的硬幣數爲 3,而最少硬幣數是 2。 
你的任務就是:對於任意的硬幣系統和一個金錢數,請你編程求出最少的找零硬幣數;
如果不能用這些硬幣找零,請給出一種找零方法,使剩下的錢最少。 
輸入 輸入數據: 
第 1 行,爲 N 和 T,其中 1≤N≤50 爲硬幣系統中不同硬幣數;1≤T≤100000 爲需要用硬幣找零的總數。 
第 2 行爲 N 個數值不大於 65535 的正整數,它們是硬幣系統中各硬幣的面值。
當n,t同時爲0時結束。 輸出 輸出數據: 
如 T 能被硬幣系統中的硬幣找零,請輸出最少的找零硬幣數。 
如 T 不能被硬幣系統中的硬幣找零,請輸出剩下錢數最少的找零方案中的最少硬幣數。 樣例輸入
4 12
10 7 5 1
樣例輸出
2

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define INF 0x3f3f3f3f  //int型內無窮大
int dp[100001];
using namespace std;
int main()
{
    int n,s,i,j;
    int coins[51];
    while(~scanf("%d%d",&n,&s))
    {
        if(n == 0&&s == 0) break;
        for(i =0; i<n; i++)
            scanf("%d",&coins[i]);
        memset(dp,INF,sizeof(dp));   //因爲要找最小值,所以初始化爲無窮大
        dp[0] = 0;           //不要忘了初始化
        for(i = 0; i<n; i++)
            for(j = coins[i]; j<=s; j++)
            {
                dp[j] = min(dp[j],dp[j-coins[i]]+1);
            }
        for(i = s; i>=0; i--)
            if(dp[i]<100001)
            {
                printf("%d\n",dp[i]);//找到最大能被換零的錢s
                break;
            }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章