C语言运用动态规划的思想解决最少硬币问题,除了输出最少硬币个数,还输出每种面额的硬币各用了多少个
最少硬币问题是一个经典的动态规划问题,可以使用动态规划思想来解决。下面给出一个 C 语言实现的代码,该代码除了输出最少硬币个数之外,还会输出每种面额的硬币各用了多少个。
#include <stdio.h>
#include <stdlib.h>
void coin_count(int *coins, int n, int target);
int main()
{
// 硬币面额数组
int coins[] = {1, 5, 10, 50};
// 数组长度
int n = sizeof(coins) / sizeof(int);
// 要凑出的金额
int target = 106;
printf("要凑出的金额为:%d\n", target);
coin_count(coins, n, target);
return 0;
}
void coin_count(int *coins, int n, int target)
{
// 动态规划数组,dp[i] 表示凑出金额 i 需要的最少硬币个数
int dp[target + 1];
// used[i] 表示凑出金额 i 使用的最后一枚硬币的面额
int used[target + 1];
// 初始化 dp 数组和 used 数组
for (int i = 0; i <= target; i++)
{
dp[i] = INT_MAX; // 设为一个极大值
used[i] = -1; // 表示没有使用任何硬币
}
dp[0] = 0; // 凑出金额为 0 不需要硬币
// 动态规划转移
for (int i = 1; i <= target; i++)
{
for (int j = 0; j < n; j++)
{
if (i >= coins[j] && dp[i - coins[j]] + 1 < dp[i])
{
dp[i] = dp[i - coins[j]] + 1;
used[i] = coins[j];
}
}
}
// 输出结果
printf("最少需要的硬币个数为:%d\n", dp[target]);
printf("使用的硬币为:");
int count[n];
for (int i = 0; i < n; i++) count[i] = 0;
int k = target;
while (k > 0)
{
int coin = used[k];
count[coin]++;
k -= coin;
}
for (int i = 0; i < n; i++)
{
if (count[coins[i]] > 0)
{
printf("%d元硬币%d枚,", coins[i], count[coins[i]]);
}
}
}
该代码中,动态规划转移的思路非常简单,就是对于每一种面额的硬币,如果能够凑出当前需要凑出的金额且使用这枚硬币后的硬币数比之前更少,则更新 dp
数组和 used
数组。
在输出结果时,我们用一个数组 count
来记录每种面额的硬币使用的数量,然后遍历一遍 count
数组输出每种面额的硬币使用的数量即可。
可参考采纳
#include <stdio.h>
#include <limits.h>
// 定义硬币面额数组和硬币种类数量
int coins[] = {1, 5, 10, 25, 50};
int num_coins = 5;
// 计算最少硬币数量和每种硬币的数量
void countCoins(int amount, int *min_num, int *coin_count) {
int i, j;
int dp[amount+1]; // 动态规划数组
int last_coin[amount+1]; // 记录最后一枚硬币面额
// 初始化动态规划数组和最后一枚硬币面额数组
for (i = 0; i <= amount; i++) {
dp[i] = INT_MAX;
last_coin[i] = -1;
}
dp[0] = 0;
// 动态规划求解最少硬币数量和每种硬币的数量
for (i = 1; i <= amount; i++) {
for (j = 0; j < num_coins; j++) {
if (coins[j] <= i && dp[i-coins[j]]+1 < dp[i]) {
dp[i] = dp[i-coins[j]] + 1;
last_coin[i] = j;
}
}
}
// 输出最少硬币数量
*min_num = dp[amount];
// 统计每种硬币的数量
for (i = 0; i < num_coins; i++) {
coin_count[i] = 0;
}
i = amount;
while (i > 0) {
coin_count[last_coin[i]]++;
i -= coins[last_coin[i]];
}
}
int main() {
int amount, min_num, coin_count[num_coins];
int i;
printf("请输入要找零的金额:");
scanf("%d", &amount);
countCoins(amount, &min_num, coin_count);
printf("最少需要 %d 枚硬币:\n", min_num);
for (i = 0; i < num_coins; i++) {
printf("%d 分硬币 %d 枚\n", coins[i], coin_count[i]);
}
return 0;
}
不知道你这个问题是否已经解决, 如果还没有解决的话:但是很多时候我们一般在结构体中定义函数指针用的比较多一点。下面再举一个简单的例子。
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
/****************************************
* 函数指针结构体 开发者写的结构体
***************************************/
typedef struct
{
uint8_t (*p_sum)(uint8_t, uint8_t);
uint8_t (*p_sub)(uint8_t, uint8_t);
uint8_t (*p_mul)(uint8_t, uint8_t);
float (*p_div)(uint8_t, uint8_t);
} Operation_T;
/*声明结构体变量g_Operation*/
Operation_T g_Operation;
/*使用者写的回调函数*/
uint8_t cal_sum(uint8_t a, uint8_t b)
{
return a + b;
}
/*使用者写的回调函数*/
uint8_t cal_sub(uint8_t a, uint8_t b)
{
return a - b;
}
/*使用者写的回调函数*/
uint8_t cal_mul( uint8_t a, uint8_t b)
{
return a * b;
}
/*使用者写的回调函数*/
float cal_div(uint8_t a, uint8_t b)
{
return a / b;
}
/*结构体变量g_Operation初始化*/
Operation_T g_Operation = {cal_sum, cal_sub, cal_mul, cal_div};
int main(void)
{
delay_init();
uart_init(9600);
printf("www.zhiguoxin.cn\r\n");
printf("微信公众号:果果小师弟\r\n");
uint8_t a = 10;
uint8_t b = 8;
/*使用函数指针调用函数*/
printf("%d\r\n", g_Operation.p_sum(a, b));
printf("%d\r\n", g_Operation.p_sub(a, b));
printf("%d\r\n", g_Operation.p_mul(a, b));
printf("%f\r\n", g_Operation.p_div(a, b));
while(1)
{
}
}
使用动态规划的思想解决最少硬币问题可以按照以下步骤进行:
以下是一个示例的C语言代码实现:
#include <stdio.h>
#include <limits.h>
int minCoins(int coins[], int n, int amount, int count[]) {
int dp[amount + 1];
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
dp[i] = INT_MAX;
for (int j = 0; j < n; j++) {
if (coins[j] <= i && dp[i - coins[j]] + 1 < dp[i]) {
dp[i] = dp[i - coins[j]] + 1;
count[i] = count[i - coins[j]] + 1;
}
}
}
return dp[amount];
}
int main() {
int coins[] = {1, 5, 10, 20}; // 硬币面额
int n = sizeof(coins) / sizeof(coins[0]); // 硬币种类数量
int amount = 47; // 目标金额
int count[amount + 1] = {0};
int minCount = minCoins(coins, n, amount, count);
printf("最少硬币个数:%d\n", minCount);
printf("每种面额的硬币使用个数:\n");
for (int i = 1; i <= amount; i++) {
printf("%d元硬币:%d个\n", coins[i - 1], count[i]);
}
return 0;
}
在上述示例代码中,我们通过minCoins
函数计算出最少硬币个数,并通过count
数组记录每种面额的硬币使用个数。然后在main
函数中输出结果。
请注意,以上代码仅为示例,实际使用时可能需要根据具体情况进行适当修改和调整。
以下是C语言的代码实现,用于解决最少硬币问题,并输出每种面额的硬币各使用了多少个。这里使用了动态规划的思想,使用了一个数组来表示所需硬币数量,数组的每个元素表示凑出相应价值所需的最少硬币数量。
#include <stdio.h>
int coin_change(int coins[], int n, int amount) {
int dp[amount + 1];
int used[amount + 1][n];
for (int i = 0; i < amount + 1; i++) {
dp[i] = i;
}
for (int i = 0; i < n; i++) {
for (int j = coins[i]; j <= amount; j++) {
if (dp[j - coins[i]] + 1 < dp[j]) {
dp[j] = dp[j - coins[i]] + 1;
for (int k = 0; k < n; k++) {
if (k == i) {
used[j][k] = used[j - coins[i]][k] + 1;
} else {
used[j][k] = used[j - coins[i]][k];
}
}
}
}
}
printf("Minimum coins needed to make amount %d: %d\n", amount, dp[amount]);
printf("Coins used:\n");
for (int i = 0; i < n; i++) {
printf("%d: %d\n", coins[i], used[amount][i]);
}
}
int main() {
int coins[] = {1, 5, 10, 25};
int n = sizeof(coins) / sizeof(coins[0]);
int amount = 37;
coin_change(coins, n, amount);
return 0;
}
在此示例中,我使用了四个不同的硬币面额,即{1, 5, 10, 25},并尝试凑出金额37。程序在函数coin_change中执行,最终得到了一个dp数组,其中dp[37] = 4,表示凑出37需要4个硬币。数组used用于记录每种硬币使用的数量,例如used[37][0] = 2,used[37][1] = 1,used[37][2] = 0,used[37][3] = 1,这表示凑出金额37需要使用2枚1美分硬币,1枚5美分硬币,0枚10美分硬币和1枚25美分硬币。
注意:这是一种基于动态规划的背包问题思想的解法,如果硬币种类特别多,可能会导致需要考虑到优化算法等问题,相应的复杂度也会更高。