一道百度面试题200元的组合方式有多少

/*************************************************
设计者:cslave
版本说明:本代码免费用于商用,拷贝,转移,使用,但是
有本代码导致的问题,本人概不负责。
设计时间:2012.7.6
分发原则:遵守GNU规范。如有错误麻烦请通知本人谢谢。
**************************************************/


/*********************************************

题目描述:

人民币有 1元 2元 5元 10元 20元 50 元 100元 这几种币值.

问:给定200元,求出有多少种币值组合方式. 币种可重复,比如,200张1元的算一种方式.


解法:
依次设 1元 2元 5元 10元 20元 50 元 100元张数为 x,y,z,m,n,p,q
则有
x+2y+5z+10m+20n+50p+100q=200 其中
0=<x<=200
0=<y=<100
0=<z=<40
0=<m=<20
0=<n=<10
0=<p=<4
0=<q=<2

可以采用for循环迭代输出的方案,但是太朴素。也可以采用
递归方案:

F(n)=F(n-1)+F(n-2)+F(n-5)+F(n-10)+F(n-20)+F(n-50)+F(n-100)

当然也可以采用自底向上的方案来输出,但是耗时都比较长


我们可以采用一种新的方案:

x+2y+5z+10m+20n+50p+100q=200 可以分治为

q=0; x+2y+5z+10m+20n+50p=200 等价于 2y+5z+10m+20n+50p<=200

q=1; x+2y+5z+10m+20n+50p=100 等价于 2y+5z+10m+20n+50p<=100

q=2: x+2y+5z+10m+20n+50p=0 只有一种选法


当q=0时

设10m+20n+50p=10k,则 2y+5z<=200-10k (0<=k<=20)

同时 2n+5p<=k;
所以
Sum=0;
for(k=0;k<=20;k++)
Sum=Count(2y+5z<=200-10k)* Count(2n+5p<=k);

当q=1时

设10m+20n+50p=10k,则 2y+5z<=100-10k (0<=k<=10)

同时 2n+5p<=k;
所以
Sum=0;
for(k=0;k<=10;k++)
Sum=Count(2y+5z<=100-10k)* Count(2n+5p<=k);

当q=2时

仅有一种方案。

Count来自于格点三角形公式,格点三角形公式是 S=E/2+I-1,
其中,E表示边界上格点数目,I表示内部的格点数目,S为格点三角形面积。
边界上格点数目为两个直角边的点数。
将格点三角形面积公式重写为
S+E/2=E/2+E/2+I-1 即为 I+E=S+E/2+1;

下面让我们想想 ,I+E为格点三角形的内部和边界顶点,他们是
满足2n+5p<=k条件的n和p的对应正整数解。

让我们通过公式计算 Count(2n+5p<=k)


对于k%10==0的情况。

E=8*M/10=4M/5 (列举2n+5p<=10想想就明白了)

S=(1/2)*(M/2)*(M/5)=M*M/20

所以I+E=S+1+E/2=M*M/20+1+2M/5


对于k%10!=0的情况 ,也就是k%10>0
2n+5p=10t+h (1 <=h <=9)。(t> =1)
当h为奇数时,p必为奇数 ,解的数目为不超过[(10t+h)/5]的所含奇数的数目

当h为偶数时,p必为偶数,解的数目为不超过[(10t+h)/5]的所含偶数的数目

[(10t+h)/5]值本身可能是2t或者2t+1;
当h=1,3时候 解的个数为t (考虑下 0 ,1,2,...,2t)

当h=2,4,5,6,7,8,9时,解的个数为t+1 (考虑下 0 ,1,2,...,2t,2t+1)


所以当h=1,2,3.。。。,9的时候,对应的解个数为
h 解个数
0 M*M/20+1+2M/5
1 t +M*M/20+1+2M/5
2 2t+1 +M*M/20+1+2M/5
3 3t+1 +M*M/20+1+2M/5
4 4t+2 +M*M/20+1+2M/5
5 5t+3 +M*M/20+1+2M/5
6 6t+4 +M*M/20+1+2M/5
7 7t+5 +M*M/20+1+2M/5
8 8t+6 +M*M/20+1+2M/5
9 9t+7 +M*M/20+1+2M/5
好了 到这里不解释了,写代码吧。

*********************************************/

View Code
 1 #include "stdafx.h"
 2 #include <iostream>
 3 using namespace std;
 4 
 5 int ComposeMoney(int Cycle)
 6 {
 7     if(Cycle%100!=0)
 8         throw exception("Cycle Is not Timesof 100!\n");
 9     int Sum=0;
10     int cycle=Cycle/10;
11     int Para1,Para2;
12     int Temp;
13     int t,h,k;
14     for(k=0;k<=cycle;k++)
15     {
16         Para1=Cycle-10*k;
17         Para2=k;
18         t=Para2/10;h=Para2%10;
19         Temp=5*t*t+1+4*t;
20         if(1<=h&&h<=2) Temp+=h*t+h-1;
21         else if(h>=3)   Temp+=h*t+h-2;
22         Sum+=Temp* (Para1*Para1/20+1+2*Para1/5);
23 
24     }
25     return Sum;
26 }
27 
28 
29 void Test()
30 {
31     try
32     {
33         int Sum=ComposeMoney(200)+ComposeMoney(100)+1;
34         cout<<Sum<<endl;
35     }
36     catch(exception& e)
37     {cout<<e.what();}
38 }
39 
40 
41 int _tmain(int argc, _TCHAR* argv[])
42 {
43     Test();
44     return 0;
45 }

如果有什么错误的地方,麻烦周知我,谢谢。

原文地址:https://www.cnblogs.com/cslave/p/2579689.html