【ProjectEuler】ProjectEuler_031

// Problem 31
// 22 November 2002
//
// In England the currency is made up of pound, O, and pence, p, and there are eight coins in general circulation:
//
// 1p, 2p, 5p, 10p, 20p, 50p, O1 (100p) and O2 (200p).
// It is possible to make O2 in the following way:
//
// 1O1 + 150p + 220p + 15p + 12p + 31p
// How many different ways can O2 be made using any number of coins?

#include <iostream>
#include <windows.h>
using namespace std;

// 采用递归的方式解决这个问题。
// remainderNum:剩余的钱数
// remainderCoins:剩余的钱币种类
// coinNum:剩余的钱币数目
// sum:总共有多少种方案了
// 每次递归只考虑一种硬币的情况,这种算法可以考虑各种硬币组合情况,适应性很广泛
void calc(int remainderNum, const int * const remainderCoins, const int coinNum, int &sum)
{
    if(coinNum == 0)		//如果没有硬币了,跳出,避免无限访问下去
    {
        return;
    }

    int maxCurrentCoins = remainderNum / remainderCoins[0];		//当前种类硬币最多的数目

    for(int i = 0; i <= maxCurrentCoins; i++)
    {
        if(remainderNum == remainderCoins[0]*i)				//如果剩余的钱刚好等于i个当前硬币的面值,则算成功匹配一次,sum自增
        {
            sum++;
            break;
        }

        calc(remainderNum - remainderCoins[0]*i, &(remainderCoins[1]), coinNum - 1, sum);		//如果不匹配,进行下一种硬币的计算
    }
}

void F1()
{
    cout << "void F1()" << endl;

    LARGE_INTEGER timeStart, timeEnd, freq;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&timeStart);

    const int coins[] = {1, 2, 5, 10, 20, 50, 100, 200};		//硬币种类

    int sum = 0;
    const int targetNum = 200;									//目的钱数

    calc(targetNum, coins, sizeof(coins) / sizeof(int), sum);	//递归计算
    cout << "总共有" << sum << "种情况" << endl;

    QueryPerformanceCounter(&timeEnd);
    cout << "Total Milliseconds is " << (double)((double)(timeEnd.QuadPart - timeStart.QuadPart) * 1000 / (double)freq.QuadPart) << endl;
}

//主函数
int main()
{
    F1();
    return 0;
}

/*
void F1()
总共有73682种情况
Total Milliseconds is 810.375

By GodMoon
2011年11月2日22:30:28
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值