题目 : 将一笔零钱换成5分、2分和1分的硬币,要求每种硬币至少有一枚,有几种不同的换法?

思路 : 由于一笔零钱,如果想换成这三种硬币的话,需要满足的条件就是5分、2分、1分的硬币加在一起正好等于零钱数,换句话说即每次零钱的一部分兑换成硬币之后所剩的零钱数一定要能够被剩下的两个硬币数所瓜分,显而易见,1分可以和任何一个其他数额的硬币去瓜分每次零钱的一部分兑换成硬币之后所剩的零钱数,因此1分就可以作为一个补充条件,放在最后保证整个程序的运行在逻辑上是行得通的。这里采用的是零钱总数兑换成5分硬币之后再让2分与1分去瓜分剩下的零钱数。

而遇到的第一个问题是5分硬币取值时他的上界是多少,无论我们从下界向上界取或说从上界往下界取,都是需要知道上界值的,毕竟下界值就是1,但上界未知。根据题目可以得知,每种硬币至少要有一枚,因此,5分 * 硬币最大个数 <= 零钱数 - (2分+1分),而由于整型的特性(可以将余数忽略),就可以通过(零钱总数-3)/5很方便的得到5分硬币最大个数,这时我们有了5分硬币的上界和下界就可以将它放入for循环中,再对2分硬币同样利用整型运算的特性执行一个类似的操作得到2分硬币的上界,最后剩下的硬币数让1分硬币入场进行补足即可.

代码如下:

#include <stdio.h>

int main() 
{
    int x,k=0,total,count=0,i,j;
    scanf("%d",&x);
    for(i=(x-3)/5;i>=1;i--)
    /*
    此处(x-3)/5由于是整型于是自动向下取整
    这样的话我就能知道5分硬币能取的上界是多少,进而从上界往下界取
    */
    {
        for(j=(x-5*i-1)/2;j>=1;j--) //同理得到j的上界
        {
            k=x-5*i-2*j;
            //1的话能够随意组合,因此他可以作为一个补充条件使结果始终成立
            total=i+j+k;
            printf("fen5:%d, fen2:%d, fen1:%d, total:%d\n",i,j,k,total);
            count++;
        }
    }
    printf("count = %d",count);
    return 0;
}

总结 : 利用整型运算忽略余数的特点,可以很方便的得到循环的上界,进而进行for循环.