程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ1837 Balance

POJ1837 Balance

編輯:C++入門知識

題目大意:

有一個天平,天平左右兩邊各有若干個鉤子,總共有C個鉤子,有G個鉤碼,求將鉤碼全部掛到鉤子上使天平平衡的方法的總數。

其中可以把天枰看做一個以x軸0點作為平衡點的橫軸

 


dp思路:

每向天平中方一個重物,天平的狀態就會改變,而這個狀態可以由若干前一狀態獲得。

 


首先定義一個平衡度j的概念:

當平衡度j=0時,說明天枰達到平衡,j>0,說明天枰傾向右邊(x軸右半軸),j<0則相反

那麼此時可以把平衡度j看做為衡量當前天枰狀態的一個值

 


因此可以定義一個 狀態數組dp[i][j],意為在掛滿前i個鉤碼時,平衡度為j的掛法的數量。

 


由於距離c[i]的范圍是-15~15,鉤碼重量的范圍是1~25,鉤碼數量最大是20

因此最極端的平衡度是所有物體都掛在最遠端,因此平衡度最大值為j=15*20*25=7500。原則上就應該有dp[ 1~20 ][-7500 ~ 7500 ]。

因此為了不讓下標出現負數,做一個處理,使使得數組開為 dp[1~20][0~15000],則當j=7500時天枰為平衡狀態

 


那麼每次掛上一個鉤碼後,對平衡狀態的影響因素就是每個鉤碼的 力臂

   力臂=重量 *臂長 = w[i]*c[k]

那麼若在掛上第i個砝碼之前,天枰的平衡度為j

   (換言之把前i-1個鉤碼全部掛上天枰後,天枰的平衡度為j)

則掛上第i個鉤碼後,即把前i個鉤碼全部掛上天枰後,天枰的平衡度 j=j+ w[i]*c[k]

     其中c[k]為天枰上鉤子的位置,代表第i個鉤碼掛在不同位置會產生不同的平衡度


不難想到,假設 dp[i-1][j] 的值已知,設dp[i-1][j]=num(即已知把前i-1個鉤碼全部掛上天枰後得到狀態j的方法有num次)

    那麼dp[i][ j+ w[i]*c[k] ] = dp[i-1][j] = num (即以此為前提,在第k個鉤子掛上第i個鉤碼後,得到狀態j+ w[i]*c[k]的方法也為num次

 


想到這裡,利用遞歸思想,不難得出 狀態方程dp[i][ j+ w[i]*c[k] ]= ∑(dp[i-1][j])

最終轉化為01背包問題

狀態方程dp[i][ j+ w[i]*c[k] ]= ∑(dp[i-1][j])

初始化:dp[0][7500] = 1;   //不掛任何重物時天枰平衡,此為一個方法


復雜度O(C*G*15000)


 

#include<iostream>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

int dp[21][15005],w[25],c[20],n,m;

int main()
{
    int i,j,k;
    while(~scanf("%d%d",&n,&m))
    {
        for(i=1;i<=n;i++)
            scanf("%d",&c[i]);
        for(i=1;i<=m;i++)
            scanf("%d",&w[i]);
        memset(dp,0,sizeof dp);
        dp[0][7500]=1;
        for(i=1;i<=m;i++)//m個物體逐個增加
        {
            for(j=0;j<=15000;j++)//增加物體產生新的平衡度 要加上原有的平衡度
            {
                if(dp[i-1][j])//優化 原有的平衡度是0的話 就不用加了 都一樣
                {
                    for(k=1;k<=n;k++)//將第i個物體放到第k個鉤上
                        dp[i][j+c[k]*w[i]]+=dp[i-1][j];
                }
            }
        }
        printf("%d\n",dp[m][7500]);
    }
    return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved