天平難題 UVa 1354

2021-08-07 12:56:56 字數 1546 閱讀 6273

給出房間的寬度r和s個掛墜的重量wi,設計乙個盡量寬(但寬度不能超過房間寬度r)的天平,掛著所有掛墜。 

天平由一些長度為1的木棍組成。木棍的每一端要麼掛乙個掛墜,要麼掛另外乙個木棍。如下圖所示,設n和m分別是兩端的總重量,要讓天平平衡,必須滿足n*a=m*b。

掛墜的寬度忽略不計,且不同的子天平可以相互重疊,下圖所示如。

輸入第一行為資料組數。每組資料前兩行為房間寬度r和掛墜數目s (0 < r < 10,1<=s<=6)。以下s行為乙個掛墜的重量wi(1<=wi<=1000)。輸入保證不存在天平的寬度恰好在r-10^(-5)和r+10^(-5)(這樣可以保證不會出現精度問題)。對於每組資料,輸出最優天平的寬度。如果無解,輸出-1。你的輸出和標準答案的絕對誤差不應超過10^(-8)。

題解:乙個天平可看做一棵二叉樹,對於乙個確定的二叉樹,可以算出每乙個掛墜的位置,那麼這個天平的寬度也可以計算出來,那麼問題就轉化成了列舉所有的二叉樹。

在這裡給出三種方法。

方法一:

自底上向上構造,每次任選擇2個掛墜合併為乙個。

#include#include#include#include#define f(i,l,r) for(i=(l);i<=(r);i++)

using namespace std;

const int maxn=8;

double w,w[maxn],ans,l[maxn],r[maxn];

int n,vis[maxn];

inline void dfs(int cur)

return;

} f(i,1,n) }}

int main()

dfs(1);

cout<

#include#include#include#include#define f(i,l,r) for(i=(l);i<=(r);i++)

#define ff(i,r,l) for(i=(r);i>=(l);i--)

using namespace std;

const int maxn=8;

double w[maxn],w,l[1

} }ans=max(ans,l[1]+r[1]);

} inline void dfs(int cur,int pos,int res)

if(~tree[cur>>1])

if(pospos) return;

f(i,1,n)

}int main()

if(n==1);

vectortree[maxn<<3];

double w[maxn],w,sum[maxn<<3],ans;

int n,vis[maxn<<3];

inline void dfs(int s)

f(i,1,(1<

UVa 1354天平難題

參考 主要思想 列舉二叉樹 計算寬度 如果只有1個葉子,直接輸出寬度為0 否則,從第2個 一定有根節點 1 開始一層一層挨個列舉編號為num的節點的值,直到用完所有w。計算寬度時,從最後乙個填入的節點往前計算以它為中心的左右的長度,左邊為負,右邊為正,一直算到根節點 num 1 r 1 l 1 就是...

練習記錄uva1354

題目 一道暴力搜尋題目,第乙個要點 列舉天平就相當列舉二叉樹。另外要記錄不同集合可以擺出的二叉樹所有狀態 偏左值,偏右值 再往上推。剛開始沒做過多少暴力搜尋題,以為像回溯法一樣找到一棵二叉樹統計寬度,在統計下一顆,貌似不太好辦。考慮到資料不大,直接記錄所有狀態即可。include include i...

UVA 1354 困難的秤 位運算列舉子集

題意 給你乙個房間的寬度和n個掛墜的重量,在滿足力矩平衡的條件下,問掛完這些掛墜不超過房間寬度的最長木棍長度之和是多少。注 每根木棍長度為一,且兩端只能懸掛掛墜或者另乙個木棍,這裡的木棍不能水平拼接!只能單獨使用!思路 因題目資料小,所以 列舉二叉樹,由小樹一步步合併為大樹,從頂部向下回溯,有點區間...