トップページに戻る    次のC++のサンプルへ    前のC++のサンプルへ

Problem31 2ポンドを作る組み合わせの数

問題

イギリスでは硬貨はポンドとペンスがあり,一般的に流通している硬貨は以下の8種類である.
1ペンス, 2ペンス, 5ペンス, 10ペンス, 20ペンス, 50ペンス, 1ポンド(100ペンス) , 2ポンド(200ペンス)

以下の方法で2ポンドを作ることが可能である.
1×1ポンド + 1×50ペンス + 2×20ペンス + 1×5ペンス + 1×2ペンス + 3×1ペンス

これらの硬貨を使って2ポンドを作る方法は何通りあるか?


ソース

#include <valarray>
#include <stack>
#include <string>
#include <Windows.h>
#include <iostream>

struct DefineKeiro{
    int X;
    std::valarray<int> MaisuuArr;
    int SumVal;
};

void main()
{
    int MoneyArr[] = {1, 2, 5, 10, 20, 50, 100, 200};
    const int MoneyArrUB = sizeof(MoneyArr)/sizeof(int)-1;

    std::stack<DefineKeiro> stk;
    for(int I=0;I<=MoneyArrUB;I++){
        DefineKeiro WillPush;
        WillPush.X = I;
        WillPush.MaisuuArr = std::valarray<int>(0,MoneyArrUB+1);
        WillPush.MaisuuArr[I] = 1;
        WillPush.SumVal= MoneyArr[I];
        stk.push(WillPush);
    }

    int AnswerCnt = 0;
    while (stk.empty() == false){
        DefineKeiro Popped = stk.top(); stk.pop();
        if (Popped.SumVal == 200) {
            std::string WillOut;
            char WKArr[100]; wsprintf(WKArr,"%d番目", ++AnswerCnt);
            WillOut += WKArr;

            for(int I=0;I<=(int)Popped.MaisuuArr.size()-1;I++){
                if(Popped.MaisuuArr[I] == 0) continue;
                wsprintf(WKArr,",%dポンドが%d",MoneyArr[I],Popped.MaisuuArr[I]);
                WillOut += WKArr;
            }
            std::cout << WillOut << std::endl;
            continue;
        }

        for (int I=Popped.X;I<=MoneyArrUB;I++) {
            DefineKeiro WillPush;
            WillPush.SumVal = Popped.SumVal + MoneyArr[I];
            if (WillPush.SumVal > 200) break;
            WillPush.X = I;
            WillPush.MaisuuArr = Popped.MaisuuArr;
            WillPush.MaisuuArr[I]++;
            stk.push(WillPush);
        }
    }
}


実行結果

省略
73675番目,1ポンドが191,2ポンドが2,5ポンドが1
73676番目,1ポンドが192,2ポンドが4
73677番目,1ポンドが193,2ポンドが1,5ポンドが1
73678番目,1ポンドが194,2ポンドが3
73679番目,1ポンドが195,5ポンドが1
73680番目,1ポンドが196,2ポンドが2
73681番目,1ポンドが198,2ポンドが1
73682番目,1ポンドが200


解説

深さ優先探索で組み合わせを列挙してます。