[编程笔记] 2018年大工博士入学考试编程题

2018年大工博士考试-编程题

10分


题目:找零钱
现在有1分、5分、1角、两角五分、五角的零钱,给出计算换零钱种类的算法。
例如:17分钱有6种换零钱的方法

1个1角 1个5分 2个1分
1个1角 7个1分
3个5分 2个1分
2个5分 7个1分
1个5分 12个1分
17个1分


(1)思路分析:

每一种方法中,有最大零钱,这个信息。
change (n, max)
change (17, 10) 有2种
change (17, 5) 有3种
change (17, 1) 有1种
所以,这是一个最大零钱逐渐变小的递归过程。

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

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

#include 

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

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

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

#include 

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 

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

你可能感兴趣的:(coding)