poj 1837 揹包(讓天平平衡的方法)

2021-06-29 04:15:47 字數 1801 閱讀 9993

題意:有乙個天平,天平左右兩邊各有若干個鉤子,總共有c個鉤子,有g個鉤碼,求將鉤碼全部掛到鉤子上使天平平衡的方法的總數。

思路:(寫的非常詳細)首先定義乙個平衡度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])

有些前輩推導方式稍微有點不同,得到的 狀態方程為dp[i][j] =∑(dp[i - 1][j - c[i] * w[i]])

可以加個優化,算出未來可能達到的最大平衡度,則此次遍歷平衡度不用從兩個端點開始了,只需從7500+-剩下的最大平衡度即可。

直接揹包:

#include #include using namespace std;

#define n 22

int dp[n][15005],w[n],c[n];

int h,n;

int test(int x)

int main()

加優化(可以刷到0ms):

#include #include #include using namespace std;

#define n 22

int dp[n][15005],w[n],c[n],sum[n];

int h,n;

int test(int x)

int cmp(int a,int b)

int main(){

int i,j,k,a,b;

scanf("%d %d",&h,&n);

for(i = 1;i<=h;i++)

scanf("%d",&c[i]);

for(i = 1;i<=n;i++)

scanf("%d",&w[i]);

sort(w+1,w+n+1,cmp);

sum[n] = w[n];

for(i = n-1;i>=2;i--)

sum[i] = sum[i+1]+w[i];

dp[0][7500] = 1;

for(i = 1;i

POJ 1837 天平問題

主要參考 題目 題意 有乙個天平,左臂右臂各長15,然後給出n,m,n代表有幾個掛鉤,掛鉤給出負數代表在左臂的距離,正數則在右臂 m代表有m個砝碼,要你求出使得這個天平保持平衡有幾種方法,要求所有砝碼全部使用完 思路 首先我們先要明確dp陣列的作用,dp i j 中,i為放置的砝碼數量,j為平衡狀態...

演算法 動態規劃poj1837

複習了動態規劃 0 1揹包問題,核心方程就是 if c i j f i j f i 1 j 如果揹包的容量,放不下c i 則不選c i else f i j max f i 1 j f i 1 j c i v i 這裡註明一點,i指代物品數量,j指代揹包容積,那麼有兩種情況,乙個是不要第i件物品,那...

POJ 1837 簡單 DP 二逼 DP

這個題,讓我看到就想到最長上公升子串行,1000的大小,n 2 就可以 但是注意到,最高的兩個士兵可以是相同身高的,所以,再求出左右兩個最長上公升子串行之後,最後得出結果的時候要注意這一點。這個地方 wa 了好多次,這個題目的通過率這麼低 應該就是這個點。include include includ...