首页 > 代码库 > 找零问题

找零问题

硬币找零问题描述:

     现存在一堆面值为 V1、V2、V3 … 个单位的硬币,问最少需要多少个硬币才能找出总值为 T 个单位的零钱?假设这一堆面值分别为 1、2、5、21、25 元,需要找出总值 T 为 63 元的零钱。

     很明显,只要拿出 3 个 21 元的硬币就凑够了 63 元了。

     基于上述动态规划的思想,我们可以从 1 元开始计算出最少需要几个硬币,然后再求 2 元、3元…每一次求得的结果都保存在一个数组中,以后需要用到时则直接取出即可。那么我们什么时候需要这些子问题的解呢?如何体现出由子问题的解得到较大问题的解呢?

     其实,在我们从 1 元开始依次找零时,可以尝试一下当前要找零的面值(这里指 1 元)是否能够被分解成另一个已求解的面值的找零需要的硬币个数再加上这一堆硬币中的某个面值之和,如果这样分解之后最终的硬币数是最少的,那么问题就得到答案了。

参考链接:http://haolloyin.blog.51cto.com/1177454/352115

// money.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

int coinValue[] = {0,1,5,10,25 };
#define kindsOfcoin 4                    //硬币种类数

//动态规划版本
void findMIn(int money)
{
	int *coinNum = new int[money + 1]();   //存储1...money找零最少需要的硬币的个数  
	int *remeCoin = new int[money + 1]();  //最后加入的硬币,方便后面输出是哪几个硬币  
	coinNum[0] =remeCoin[0] = 0;

	for (int i = 1; i <= money; i++)          //i面值钱,需要最少硬币个数
	{
		int minNum = i;       
		int useCoin = 0;      //这次找零,在原来的基础上需要的硬币           

		for(int j=1;j<=kindsOfcoin;j++)
			if(i>=coinValue[j])
				//需要判断i - coinValue[j]是否能找的开,如果找不开,就不需要更新。
				if ((minNum > coinNum[i - coinValue[j]] + 1) && (i == coinValue[j] || remeCoin[i - coinValue[j]] != 0))
				{
					minNum = coinNum[i - coinValue[j]] + 1;
					useCoin = coinValue[j];
				}
		coinNum[i] = minNum;
		remeCoin[i] = useCoin;
	}

	if (remeCoin[money] == 0)
		cout << "找不开零钱" << endl;
	else
	{
		cout << "需要最少的硬币个数为:" << coinNum[money] << endl;
		cout << "所用到的硬币为:"<<endl;
		while (money > 0)
		{
			cout << remeCoin[money] << ‘\t‘;
			money -= remeCoin[money];
		}
	}
	delete[]coinNum;
	delete[]remeCoin;
}

int main()
{
	cout << "请输入需要找零的金额" << endl;;
	int money;
	cin >> money;
	findMIn(money);
	while (1);
    return 0;
}

  

找零问题