读博士-[入学考试编程题]找零钱

现在有1分、5分、1角、两角五分、五角的零钱,给出计算换零钱种类的算法。

例如:17分钱有6种换零钱的方法

1角 5分 2分

1角 7分

3*5分 2*1分

2*5分 7*1分

1*5分 12*1分

17分

(1)思路分析:

每一种方法中,有最大零钱,这个信息。

change (n, max)

扫描二维码关注公众号,回复: 2564259 查看本文章

change (17, 10) 有2种

change (17, 5) 有3种

change (17, 1) 有1种

所以,这是一个最大零钱逐渐变小的递归过程。

考虑这样的可能性,17分钱换出一个1角,后变成了7分钱换零钱的问题,即(17,10)->(7,5) and (7,1)。但其实,这里有坑不是直接变的。

只计算有多少种换零钱的方法,而不考虑具体的数额。代码:

#include <stdio.h>

int c[5] = {1, 5, 10, 25, 50};

int change(int n, int i){
    if(0 == n) return 0;
    if(0 == i) return 1;
    if(n<c[i]) return change(n, i-1);
    return change(n, i-1) + change(n-c[i], i);
}

int main(void) {
    // your code goes here
    printf("%d\n", change(17, 4));
    return 0;
}

(2)分析:顺着思路想,其实这个问题可以画出一棵树,树的叶子节点的个数就是解。那么,其实问题的本质就是一个二叉树的搜索问题,求叶子节点个数的问题。而,每一条路径对应的就是每种换零钱方式的具体数额。

考虑使用一种void类型的函数实现。就需要用一个显示的变量来存储这个方法种类个数。另外,零钱集合可以放在数组中,只要传递一个数组指针给函数。

#include <stdio.h>

void change(int n, int *c, int i, int *sum){
    if(0 == n) return;
    if(0 == i) {
        *sum += 1;
        return;
    }
    change(n, c, i-1, sum);
    if(n >= c[i])
    change(n-c[i], c, i, sum);
}

int main(void) {
    // your code goes here
    int c[5] = {1, 5, 10, 25, 50};
    int sum = 0;
    change(17, c, 4, &sum);
    printf("%d\n", sum);
    return 0;
}

(3)问题:如何输出每种换零钱的具体数额。

类似于二叉树的深度优先搜索,每搜索到一个叶子节点就输出该路径。一条路径结束之后,要回退。常用的操作就是,栈的push和pop操作。这里只需要对零钱的数字进行加减就行。

要输出每种零钱的具体换算数额,需要创建一个数组来保存数据。

假设数组为A[5] ={0}, A[i]保存C[i]的个数。

#include <stdio.h>

void change(int n, int *c, int i, int *sum, int *a){
    if(0 == n) return;
    if(0 == i) {
        *sum += 1;
        a[i] = n;
        print(c, a, 4);
        a[i] = 0;
        return;
    }
    if(n >= c[i]){
        a[i]++;
        // 如果剩余的钱大于最大零钱,减去,继续搜索
    change(n-c[i], c, i, sum, a);
    a[i]--;
    }
    // 如果剩余的钱小于最大零钱,降级,继续搜索
    change(n, c, i-1, sum, a);
}

void print(int *c, int *a, int n){
    for(int i=n-1; i>=0; i--){
        if(a[i])
        printf("%d%d分\t", a[i], c[i]);
    }
    printf("\n");
}

int main(void) {
    // your code goes here
    int a[5] = {0};
    int c[5] = {1, 5, 10, 25, 50};
    int sum = 0;
    change(30, c, 4, &sum, a);
    printf("一共有%d种换零钱的方式。", sum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cp_oldy/article/details/81412488