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

2021-08-20 02:10:43 字數 1534 閱讀 4379

題意:給你乙個房間的寬度和n個掛墜的重量,在滿足力矩平衡的條件下,問掛完這些掛墜不超過房間寬度的最長木棍長度之和是多少。注:每根木棍長度為一,且兩端只能懸掛掛墜或者另乙個木棍,這裡的木棍不能水平拼接!只能單獨使用!

思路:因題目資料小,所以 - 〉列舉二叉樹,由小樹一步步合併為大樹,從頂部向下回溯,有點區間dp的感覺

收穫技巧:

1.位運算如何列舉二叉樹?

我們用二進位制對應i位上表示這個子樹掛不掛第i個掛墜,然後列舉這個二進位制的所有子集為左子樹,那麼他的對稱差集就是右子樹,然後構成這棵子樹的不同樹形,每一種合格的樹形都存在tree[這個二進位制集合]裡,那麼同理,最後tree[全集]存的就是掛墜全掛上的時候的所有樹形,這時候只要列舉每乙個樹形的lift+right長度,取最大的即可!

2.對於每一棵子樹怎麼求他的長度?

所以要綜合判斷: t.l = max(tree[lefted][i].l+lf,tree[righted][j].l-lr);

t.r = max(tree[righted][j].r+lr,tree[lefted][i].r-lf);

3.如何列舉子集?

for(int lefted = (father-1)&father;lefted;lefted = (lefted-1)&father)

int righted = father^lefted;構造差集

**:

#include #includeusing namespace std;

double r;

int n;

struct tree

};double w[6];

double sum[150];

bool vis[150];

vectortree[150];

void dfs(int father){

if(vis[father])return;

vis[father] = 1;//剪枝,已經判斷了的直接結束

bool judge = false;//是否有子集

for(int lefted = (father-1)&father;lefted;lefted = (lefted-1)&father)//列舉子集

{judge = true;

int righted = father^lefted;//取差集

double lf = sum[righted]/sum[father];//左子集在father杆的左側長度

double lr = sum[lefted]/sum[father];//右子集在father杆的右側長度

dfs(righted);

dfs(lefted);//下面構造father樹下所有可能的由左右子集構成的樹形

for(int i = 0;i

天平難題 UVa 1354

給出房間的寬度r和s個掛墜的重量wi,設計乙個盡量寬 但寬度不能超過房間寬度r 的天平,掛著所有掛墜。天平由一些長度為1的木棍組成。木棍的每一端要麼掛乙個掛墜,要麼掛另外乙個木棍。如下圖所示,設n和m分別是兩端的總重量,要讓天平平衡,必須滿足n a m b。掛墜的寬度忽略不計,且不同的子天平可以相互...

練習記錄uva1354

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

UVa 1354天平難題

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