1. 程式人生 > >1分2分5分的硬幣,組成1角,共有多少種組合

1分2分5分的硬幣,組成1角,共有多少種組合

設1分個數為x,2分個數為y,5分的硬幣個數為z,則1*x+2*y+5*z=10;
5*z=10-x-2*y;即:
z x對應可能的取值

z=0   10 8 6 4 2 0(6個)
z=1   5 3 1(3個)
z=2   0(1個)
總共個數為6+3+1=10.
因此,按照規律,本題目組合總數為10以內的偶數+5以內的奇數+0以內的偶數
某個偶數m以內的偶數個數(包括0)可以表示為m/2+1=(m+2)/2
某個奇數m以內的奇數個數也可以表示為(m+2)/2


所以,求總的組合次數可以程式設計為:
number=0;
for (int m=0;m<=10;m+=5)
{
number+=(m+2)/2;
}
cout<<number<<endl;


這樣程式是不是簡單多了(只需要累加3次,而上面的3層迴圈呢?大家自己想想)。別人考你肯定不是考你會不會編這個程式,是考你如何去使程式的複雜度降低。

6分、4分、2分組成100分怎麼處理?

2分為x,4分為y,6分為z。則6*z=100-2*x-4*y,可化簡為:
3*z=50-x-2*y
z可能的取值為0、1、2···16,
當z=0時,x可以為50 48 46···2 0(26個)
當z=1時,x可以為47 45 43···3 1(24個)
當z=2時,x可以為44 42 40···2 0(23個)
當z=3時,x可以為41 39 37···3 1(21個)
·
·
·
當z=15時,x可以為5 3 1(3個)
當z=16時,x可以為2 0(2個)

因此,按照規律,本題目組合總數為50以內的偶數+47以內的奇數+44以內的偶數+···+5以內的奇數+2以內的偶數
某個偶數m以內的偶數個數(包括0)可以表示為m/2+1=(m+2)/2
某個奇數m以內的奇數個數也可以表示為(m+2)/2

所以,求總的組合次數可以程式設計為:
number=0;
for (int m=0;m<=50;m+=3)
{
number+=(m+2)/2;
}
cout<<number<<endl;

是不是可以看出規律了呢?實際上就是看錶達式(這裡是3*z=50-x-2*y),就是把最大乘數(這裡是3)放在一邊,這也是m增加的步長。而m的最大取值也就是表示式中的這個常數。

當然這也是個典型的揹包問題:

int dp[10+1];

int main()
{
    int w[] = {1,2,5};
    dp[0] = 1;
    for(int i=0; i<3; i++)
    {
        for(int j=w[i]; j<=10; j++)
        {
            dp[j] += dp[j - w[i]];
        }
    }
    printf("%d\n",dp[10]);
    return 0;
}