砝碼稱重問題求解:動態規划與母函數方法


  砝碼稱重問題:設有1g2g3g5g10g20g的砝碼各若干枚(其質量<=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個。

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM