砝碼稱重問題:設有1g、2g、3g、5g、10g、20g的砝碼各若干枚(其質量<=1000g),求出用他們能稱出的質量的種類數(不包括質量為0的情況)。
一、動態規划方法求解
設dp[1000]數組為標記數組。當dp[i]=0時,表示質量為i的情況,目前沒有稱出;當dp[i]=1時,表示質量為i的情況已經稱出。
本題目中有多個砝碼,我們順序處理每一個砝碼。
當處理第j個砝碼,質量為wj時,有下列推導公式:
完整程序代碼如下:
#include<stdio.h> #include<string.h> int sum; ///表示輸入的砝碼的總質量 int ma[6]; ///六種砝碼的個數 int weight[6]={1,2,3,5,10,20}; ///六種砝碼的重量 char dp[1001]; ///標記位 void input(); ///輸入每個砝碼的數量,並求出所有砝碼的總質量sum void exeDP(); void output(); ///判斷標記為1的數量,並輸出 int main() { memset(dp,0,sizeof(dp)); input(); exeDP(); output(); return 0; } void input() { int i; sum=0; for(i=0;i<6;i++) { scanf("%d",&ma[i]); sum=sum+(ma[i]*weight[i]); } } void exeDP() { int i,j,z; dp[0]=1; for(i=0;i<6;i++) ///六種砝碼 { for(j=0;j<ma[i];j++) ///每種砝碼的個數 { for(z=sum;z>=weight[i];z--) ///判斷每種質量是否可以被稱出 { if(dp[z-weight[i]]==1) dp[z]=1; } } } } void output() { int i,time=0; for(i=1;i<=sum;i++) { if(dp[i]==1) ///若能被稱出,則計數 time++; } printf("%d",time); }
二、母函數求解
設輸入的質量為w的砝碼n個,則可以用母函數表示為:
針對本題目,例如輸入六種砝碼(1g,2g,3g,5g,10g,20g)的個數分別為:1,2,2,0,0,1。則有:
用matlab軟件的符號計算有:
>> syms x; >> f1=(1+x); >> f2=(1+x^2+x^4); >> f3=(1+x^3+x^6); >> f4=(1+x^20); >> expand(f1*f2*f3*f4)
>>ans=
x^31 + x^30 + x^29 + 2*x^28 + 2*x^27 + 2*x^26 + 2*x^25 + 2*x^24 + 2*x^23 + x^22 + x^21 + x^20 + x^11 + x^10 + x^9 + 2*x^8 + 2*x^7 + 2*x^6 + 2*x^5 + 2*x^4 + 2*x^3 + x^2 + x + 1
其中x的指數就是能夠稱出的質量,可知可以稱出的不同質量個數為23個。