この問題は少なくとも2方向のアプローチがあり、面白いと思いました。中級以上の人向けかなと。この質問者のレベルで、なぜこんな問題を解かにゃならんの?
- 目的の金額をこれらの紙幣の組合わせで作れないか、バックトラック法で探す。
自然なアプローチに思えますが、再帰を使うので初心者向きかな?と疑問。
- 金額(1円〜500円程度)をインデックスにして、払える・払えないの配列を作る。それには予め7枚の紙幣で払える全ての組み合わせ金額を総当りで挙げれば良い。
一旦その配列を作ってしまえば、目的の金額が払える・払えないの判定は一瞬。
forループ一個で全ての組み合わせを総当り検査するという方法は、C言語でナップザック問題 総当たりで悩んでいますで使ったものです。
この時、再帰で調べる方法を示した方がいらっしゃいました。再帰ですから、私のバックトラック法に相当するようです。
ソートの手段もいろいろ選べます。私はqsort()を使う方法と、支払えないと判定した金額を、単方向リストの適切な位置に挿入することでソートしてしまう方法を試しました。コードは書けたので、そのプログラムの動作中の様子を表示して途中のデータの様子などを見てもらってイメージだけでも掴んでもらおうと思ったのですが、気づいたら既に質問者のアカウントが凍結されていたというお粗末(苦笑)。
izmktrさん
組み合わせは2^7=128 なんで、全通り求めてしまえばいい
それが私の試した方法のひとつなので、私もその一部をアップします。
金額(1円〜500円程度)をインデックスにして、払える・払えないの配列を作る…
C
1#include <stdio.h>
2#include <stdbool.h>
3int target_prices[] = {
4 299, 111, 128, 71, 328, 255, 239, 260,
5 151, 163, 246, 184, 253, 97, 78, 114,
6};
7int bills[] = { 3, 6, 11, 28, 57, 86, 119 };
8bool able2pay[500]; // 最初は全て支払い不能(0〜499円に対して)
9#define N_BILLS (sizeof(bills) / sizeof(bills[0]))
10#define N_PRICES (sizeof(target_prices) / sizeof(target_prices[0]))
11int main(void)
12{
13 // 7枚の札、全ての組合せを調べ、支払い可能な金額は true
14 printf("1. build the flag table.\n");
15 for (int i = 1; i < (1 << N_BILLS); ++i) {
16 int mask = 1, sum = 0;
17
18 for (int j = 0; j < N_BILLS; ++j, mask += mask) {
19 if (i & mask)
20 sum += bills[j]; // この組み合わせに含まれる金額を足す
21 }
22 able2pay[sum] = true; // 合計金額sum円は支払い可能
23 }
24
25 printf("2. prices unable to pay are\n");
26 for (int i = 0; i < N_PRICES; ++i) {
27 if (! able2pay[target_prices[i]])
28 printf(" %d", target_prices[i]);
29 }
30 printf("\n");
31
32 printf("TODO: sort above.\n");
33 return 0;
34}