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