teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

コードを一部公開

2020/02/05 03:30

投稿

rubato6809
rubato6809

スコア1382

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