1. 程式人生 > >最少錢幣數-貪心演算法-CCF-CSP練習題

最少錢幣數-貪心演算法-CCF-CSP練習題

目錄

題目:

分析:

總結:

來自湖大程式設計訓練系統(外網進不去,所以不貼連結了)。

題目:

最少錢幣數
問題描述 這是一個古老而又經典的問題。用給定的幾種錢幣湊成某個錢數,一般而言有多種方式。例如:給定了 6 種錢幣面值為 2、5、10、20、50、100,用來湊 15 元,可以用 5 個 2 元、1個 5 元,或者 3 個 5 元,或者 1 個 5 元、1個 10 元,等等。顯然,最少需要 2 個錢幣才能湊成 15 元。         你的任務就是,給定若干個互不相同的錢幣面值,程式設計計算,最少需要多少個錢幣才能湊成某個給出的錢數。
輸入形式 輸入可以有多個測試用例。每個測試用例的第一行是待湊的錢數值 M(1 <= M<= 2000,整數),接著的一行中,第一個整數 K(1 <= K <= 10)表示幣種個數,隨後是 K個互不相同的錢幣面值 Ki(1 <= Ki <= 1000)。輸入 M=0 時結束。
輸出形式 每個測試用例輸出一行,即湊成錢數值 M 最少需要的錢幣個數。如果湊錢失敗,輸出“Impossible”。你可以假設,每種待湊錢幣的數量是無限多的。
樣例輸入 15 6 2 5 10 20 50 100 1 1 2 0
樣例輸出 2 Impossible

分析:

要想錢幣數最少,緊著最大面值的錢用,當前剩餘的錢數小於最大面值的錢的話就用第二大面值,以此類推,直到待湊的錢數值為0,或者不為0(則輸出Impossible)。基於這種想法,演算法上叫貪心演算法,我們還可以每次都算一次Money除以maxCoins最大面值的錢數值,得到用幾張最大錢幣,餘數即為剩餘錢幣數,這樣我們只用迴圈錢幣種數k次就能得出答案。

minCoin += money/coins[i]; //錢幣數
money = money%coins[i];    //剩餘錢數

C++程式碼:

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    bool cmp(int a,int b);//降序排序比較函式
    int coins[10];//硬幣數目,由於題目給出不超過10種,所以我申請了10。
    int money; /*待湊錢的數值*/
    int kind;  /*錢幣種類數目*/
    int minCoin =0 ;//最少錢幣數
    int i;
    while(1)
    {
        minCoin = 0;//每次初始化為0
        cin >> money;     //讀入待湊錢數
        if(0 == money) break; //如果為0,則退出。
        cin >> kind;          //讀入擁有錢幣種類數
        for(i=0; i<kind; i++)
        {
            cin >> coins[i];  //依次讀入錢幣種類
        }
        sort(coins,coins+kind,cmp);  //降序排序錢幣種類
        for(i=0; i<kind; i++)
        {
            if(money-coins[i] >= 0)
            {
                minCoin += money/coins[i];
                money = money%coins[i];
            }
        }
        if( 0 == money )
        {
            cout << minCoin << endl;
        }else{
            cout << "Impossible" <<endl;
        }

    }
    return 0;
}

bool cmp(int a,int b) /* 降序排序比較函式,當a>b時,不交換;當a<b時交換*/
{
    return a > b;
}

總結:

這個解法在oj系統中有問題,只得了50分,剩下的每組資料有1個是錯誤的,目前還沒有找到哪出了問題。接下來研究研究使用動態規劃法解決這個問題。