兑换硬币问题
兑换硬币问题是C语言的一个经典问题。题目如下:
现有一张1元纸币,欲将其兑换为1分、2分、5分硬币共60枚,请列出所有兑换方案。
我们可以利用分支和循环来解决这个问题。
最简单的方法——三重循环法
最“无脑”也是最容易想到的方法是利用三重循环。其代码如下所示:
#include <stdio.h>
int main (void)
{
int i = 0;
int one, two, five;
for (one = 0; one <= 60; one++)
{
for (two = 0; two <= 50; two++)
{
for (five = 0; five <= 20; five++)
{
if ((one * 1 + two * 2 + five * 5 == 100) && (one + two + five == 60))
{
i++;
printf ("兑换方案%2d:1分硬币%2d枚,2分硬币%2d枚,5分硬币%2d枚\n", i, one, two, five);
}
}
}
}
printf ("共有%d种兑换方案\n", i);
return 0;
}
输出结果如下:
兑换方案 1:1分硬币20枚,2分硬币40枚,5分硬币 0枚
兑换方案 2:1分硬币23枚,2分硬币36枚,5分硬币 1枚
兑换方案 3:1分硬币26枚,2分硬币32枚,5分硬币 2枚
兑换方案 4:1分硬币29枚,2分硬币28枚,5分硬币 3枚
兑换方案 5:1分硬币32枚,2分硬币24枚,5分硬币 4枚
兑换方案 6:1分硬币35枚,2分硬币20枚,5分硬币 5枚
兑换方案 7:1分硬币38枚,2分硬币16枚,5分硬币 6枚
兑换方案 8:1分硬币41枚,2分硬币12枚,5分硬币 7枚
兑换方案 9:1分硬币44枚,2分硬币 8枚,5分硬币 8枚
兑换方案10:1分硬币47枚,2分硬币 4枚,5分硬币 9枚
兑换方案11:1分硬币50枚,2分硬币 0枚,5分硬币10枚
共有11种兑换方案
稍加改进——双重循环法
通过分析上面的程序,我们可以发现,通过利用变量one,two和five之间的关系,即one+two+five=60,我们可以减少一层循环,从而达到代码的优化。改进后的代码如下:
#include <stdio.h>
int main(void)
{
int i = 0;
int one, two, five;
for (five = 0; five < 20; five++)
{
for (two = 0; two < 50; two++)
{
one = 60 - two - five;
if (one + two * 2 + five * 5 == 100)
{
i++;
printf ("兑换方案%2d:1分硬币%2d枚,2分硬币%2d枚,5分硬币%2d枚\n", i, one, two, five);
}
}
}
printf ("共有%d种兑换方案\n", i);
return 0;
}
输出结果如下:
兑换方案 1:1分硬币20枚,2分硬币40枚,5分硬币 0枚
兑换方案 2:1分硬币23枚,2分硬币36枚,5分硬币 1枚
兑换方案 3:1分硬币26枚,2分硬币32枚,5分硬币 2枚
兑换方案 4:1分硬币29枚,2分硬币28枚,5分硬币 3枚
兑换方案 5:1分硬币32枚,2分硬币24枚,5分硬币 4枚
兑换方案 6:1分硬币35枚,2分硬币20枚,5分硬币 5枚
兑换方案 7:1分硬币38枚,2分硬币16枚,5分硬币 6枚
兑换方案 8:1分硬币41枚,2分硬币12枚,5分硬币 7枚
兑换方案 9:1分硬币44枚,2分硬币 8枚,5分硬币 8枚
兑换方案10:1分硬币47枚,2分硬币 4枚,5分硬币 9枚
兑换方案11:1分硬币50枚,2分硬币 0枚,5分硬币10枚
共有11种兑换方案
我们得到了相同的输出结果,可见这种想法是可行的。
最优方法——单重循环法
实际上,这道题只用单重循环也是可以解决的。
我们再次对变量one,two和five之间的关系进行分析,不难得出以下两个关系式:
one + two + five = 60
one + two × 2 + five × 5 = 100
整理之后,得:
two + five × 4 = 40,即 two = 40 - five × 4
five ≤ 10
根据上面的分析,我们可以再次优化代码,如下所示:
#include <stdio.h>
int main(void)
{
int i = 0;
int one, two, five;
for (five = 0; five <= 10; five++)
{
two = 40 - 4 * five;
one = 60 - two - five;
if (one + two * 2 + five * 5 == 100)
{
i++;
printf ("兑换方案%2d:1分硬币%2d枚,2分硬币%2d枚,5分硬币%2d枚\n", i, one, two, five);
}
}
printf ("共有%d种兑换方案\n", i);
return 0;
}
输出结果依旧和上面的两个程序相同:
兑换方案 1:1分硬币20枚,2分硬币40枚,5分硬币 0枚
兑换方案 2:1分硬币23枚,2分硬币36枚,5分硬币 1枚
兑换方案 3:1分硬币26枚,2分硬币32枚,5分硬币 2枚
兑换方案 4:1分硬币29枚,2分硬币28枚,5分硬币 3枚
兑换方案 5:1分硬币32枚,2分硬币24枚,5分硬币 4枚
兑换方案 6:1分硬币35枚,2分硬币20枚,5分硬币 5枚
兑换方案 7:1分硬币38枚,2分硬币16枚,5分硬币 6枚
兑换方案 8:1分硬币41枚,2分硬币12枚,5分硬币 7枚
兑换方案 9:1分硬币44枚,2分硬币 8枚,5分硬币 8枚
兑换方案10:1分硬币47枚,2分硬币 4枚,5分硬币 9枚
兑换方案11:1分硬币50枚,2分硬币 0枚,5分硬币10枚
共有11种兑换方案