貪心法 貨幣支付問題或找零問題


 已知,中華人民共和國的紙幣面額分別為:100元、50元、20元、10元、5元、2元、1元,輸入錢數,輸出最小的貨幣方案。

 

#include<iostream>
using namespace std;
int denomination[7]={100,50,20,10,5,2,1};

int  giveChange(int money,int (*result)[2])
{
     
    int k=0;
    int sum=0;
    for(int i=0;i<7;i++)
    {
        if(money==0) break;
        if(money/denomination[i] > 0)
        {
            sum+=money/denomination[i] * denomination[i];
            result[k][0]=denomination[i];
            result[k][1]=money/denomination[i];
            money=money-sum;
            k++;
            
        }
     
    }
    return k;
}

int main()
{
    int n; //錢總數
    
    while(cin>>n)
    {
     
        int result[100][2];
        int k=giveChange(n,result);
        cout<<"需要"<<k<<""<<endl;
        for(int i=0;i<k;i++)
        {
            cout<<result[i][0]<<"面幣"<<result[i][1]<<""<<endl;
        }
        cout<<endl;
    }
}

 

或:

//find_change.cpp
/*
找零錢問題:
    以人民幣1元,2元,5元,10元,20元,50元,100元為例,要求所找的張數最少.
貪心解法:
    要找N分錢,先拿N除最大零錢面值,取整就是所找的最大面值零錢的個數,取模得
    出余數重新賦給N.重復操作直到除最小面值結束. 
*/
#include<iostream>
using namespace std;
int main()
{
    int n, i;
    const int parValue[7] = {100,50,20,10,5,2,1};//面值從大到小排列
    int cnt, anNumber[7];//找錢方案,各幣值數量
    while(cin>>n && n) {
        memset(anNumber, 0, 7*sizeof(int));
        
        i = 0, cnt = 0;
        while (n > 0) {
           anNumber[i] = n/parValue[i];
            n = n%parValue[i];
            cnt += anNumber[i];
            ++i;
        }
        
        //輸出
        cout<<"面 值:100 50 20 10 5   2   1"<<endl;
        cout<<"找零數:";
        for (i = 0; i < 7; ++i) {
            printf("%-3d ", anNumber[i]);
        }
        cout<<endl;
        cout<<"需找錢張數:"<<cnt<<endl;
    }
    return 0;
}

 

參考了:

http://blog.csdn.net/cxxsoft/article/details/935835

貪心算法在 這種方法在這里之所以總是最優,是因為銀行對其發 行的硬幣種類和硬幣面值的巧妙安排。
  如果只有面值分別為1,5和11單位的硬幣,而希望找 回總額為15單位的硬幣,按貪婪算法,應找1個11單位 面值的硬幣和4個1單位面值的硬幣,共找回5個硬幣。 但最優的解答應是3個5單位面值的硬幣。

證明人民幣找零問題貪心算法的正確性

問題提出:

根據人們生活常識,我們到商店里買東西需要找零錢時,收銀員總是先給我們最大面值的,要是不夠再找面值小一點的,直到找完為止。這就是一個典型的貪心選擇問題。 問題描述:

當前有面值分別為100 元、50 元、20 元、10 元、5元、1元, 5角, 2角、1角的人民幣。證明人民幣在找零時(1-99元)符合貪心算法,即證明此問題滿足貪心算法的兩個基本要素:即最優子結構性質和貪心選擇性質。

問題證明:

當一個問題的最優解包含其子問題的最優解時,稱此問題具有最優子結構性質。在人民幣找零問題中,其最優子結構性質表現為:

設c[i]是各面額人民幣使用的數量,S[i]是商品價格為n時的最優解,數量為K。現在設某面值的人民幣數量減一:S[j]=S[j]-1,則新的S[i]為n-c[j]的最優解,紙幣數K-1. 否則,設T[i]是n-c[j]的最優解,紙幣數為m,即m<k-1.那么對於n來說,T[i]+1應該為原問題最少紙幣數,即m+1<k-1+1=k,此與k為最少紙幣數矛盾,故問題滿足最優子結構性質。 貪心選擇性質是指所求問題的整體最優解可以通過一系列局部最優的選擇,即貪心選擇來達到。在人民幣找零問題中,滿足貪心選擇性質的證明如下:

設紙幣面額100,50,20,10,5,2,1元的數量依次為A,B,C,D,E,F,G,則根據貪心算法思想得到的解應依次保證max(A),max(B),max(C),max(D),max(E),max(F),max(G)。假設存在更優的算法,使得所用的紙幣數更少,即數量至少小於或等於A+B+C+D+E+F+G-1。那么在紙幣總數減少的情況下保證總額不變只能增大相對大面額紙幣的數量並減少小面額紙幣數量。而由貪心算法知max(A)已經是最大的了,以此類推,max(B),max(C),max(D),max(E),max(F)均應為最大數量了,所以貪心算法得到的解是最優解,即滿足貪心選擇性質。

綜上所述,人民幣找零問題滿足貪心算法。

 

帖子:請教,一個問題滿足什么樣的條件才能保證貪心算法可以得出最優解?
在看書的時候遇到一個“找零錢”問題:目標是找67分,面值有25、10、5、2、1,目標是所用硬幣數量最少。此問題用貪心可得最優解,即每次拿出不會導致總面值超過目標面值的最大面值:25+25+10+5+2=67。
但是,如果換成目標面值10分,面值種類有7、5、1,那么貪心法就不好用了,因為7+1+1+1=5+5。
想到這里,就想請教大家,一個問題滿足什么樣的條件才能保證貪心算法可以得出最優解?
我想應該有比較簡潔的結論吧。
謝謝。

參考:http://bbs.csdn.net/topics/330085072


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM