#include #include #include #include #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; }