90 lines
2.4 KiB
C
90 lines
2.4 KiB
C
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define DEBUG 0
|
|
#define IMPOSSIBLE (INT_MAX >> 1)
|
|
|
|
int main(int argc, char **argv) {
|
|
int num_coins, amount;
|
|
int *coins;
|
|
int *m;
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr, "Usage: %s NUM_COINS [COINS ...]\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
amount = atoi(argv[1]);
|
|
|
|
num_coins = argc - 2;
|
|
coins = malloc(num_coins * sizeof(int));
|
|
for (int i = 0; i < num_coins; i++) {
|
|
coins[i] = atoi(argv[i + 2]);
|
|
}
|
|
|
|
m = calloc((num_coins + 1) * (amount + 1), sizeof(int));
|
|
for (int j = 1; j < amount + 1; j++) {
|
|
m[j * (num_coins + 1)] = IMPOSSIBLE;
|
|
}
|
|
|
|
for (int i = 1; i < num_coins + 1; i++) {
|
|
int coin = coins[i - 1];
|
|
for (int r = 1; r < amount + 1; r++) {
|
|
if (coin == r) {
|
|
m[r * (num_coins + 1) + i] = 1;
|
|
} else if (coin > r) {
|
|
m[r * (num_coins + 1) + i] = m[r * (num_coins + 1) + i - 1];
|
|
} else {
|
|
int solution_a = m[r * (num_coins + 1) + i - 1];
|
|
int solution_b = 1 + m[(r - coin) * (num_coins + 1) + i];
|
|
if (solution_a < solution_b) {
|
|
m[r * (num_coins + 1) + i] = solution_a;
|
|
} else {
|
|
m[r * (num_coins + 1) + i] = solution_b;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DEBUG) {
|
|
for (int i = 1; i < num_coins + 1; i++) {
|
|
for (int j = 0; j < amount + 1; j++) {
|
|
if (m[j * (num_coins + 1) + i] == IMPOSSIBLE) {
|
|
printf("---- ");
|
|
} else {
|
|
printf("%4d ", m[j * (num_coins + 1) + i]);
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
int i = num_coins;
|
|
int j = amount;
|
|
char output[256] = "";
|
|
char *cur = output, *const end = output + sizeof(output);
|
|
|
|
while (j != 0) {
|
|
int coin = coins[i - 1];
|
|
if (j >= coin && m[(j - coin) * (num_coins + 1) + i] == m[j * (num_coins + 1) + i] - 1) {
|
|
if (j == coin) {
|
|
printf("%s%d\n", output, coin);
|
|
} else {
|
|
cur += snprintf(cur, end - cur, "%d, ", coin);
|
|
}
|
|
j -= coin;
|
|
} else if (i > 0) {
|
|
i--;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(m);
|
|
free(coins);
|
|
|
|
return 0;
|
|
}
|