UVa1354 Mobile Computing (枚举二叉树)

链接:http://acm.hust.edu.cn/vjudge/problem/41537分析:二进制法枚举二叉树。用n位二进制位代表n个元素,第i位为1代表集合中包含第i个元素,否则不包含。从右往左依次表示第0,1,2,3...n-1号元素,sum表示包含集合中的元素时的总重量,tree[subset]表示包含集合中的元素时天平合法的L和R,vis表示当前子集是否已经被枚举过避免重复枚举。然后就是dfs递归枚举子集,枚举左子树的集合剩下的就是右子树,然后继续递归枚举,枚举到叶子结点或vis为true时终止且叶子结点的L和R为0,然后循环遍历subset的left和right,将subset下合法的L和R存到tree[subset]中。最后找到tree[root]中最大的L+R就是答案。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 using namespace std;
 5
 6 struct Tree {
 7   double L, R;
 8   Tree():L(0),R(0) {}
 9 };
10
11 const int maxn = 6;
12
13 int n, vis[1 << maxn];
14 double r, w[maxn], sum[1 << maxn];
15 vector<Tree> tree[1 << maxn];
16
17 void dfs(int subset) {
18   if(vis[subset]) return;
19   vis[subset] = true;
20   bool have_children = false;
21   for (int left = (subset - 1) & subset; left; left = (left - 1) & subset) {
22     have_children = true;
23     int right = subset ^ left;
24     double d1 = sum[right] / sum[subset];
25     double d2 = sum[left] / sum[subset];
26     dfs(left); dfs(right);
27     for(int i = 0; i < tree[left].size(); i++)
28       for(int j = 0; j < tree[right].size(); j++) {
29         Tree t;
30         t.L = max(tree[left][i].L + d1, tree[right][j].L - d2);
31         t.R = max(tree[right][j].R + d2, tree[left][i].R - d1);
32         if(t.L + t.R < r) tree[subset].push_back(t);
33       }
34   }
35   if(!have_children) tree[subset].push_back(Tree());
36 }
37
38 int main() {
39   int T;
40   scanf("%d", &T);
41   while(T--) {
42     scanf("%lf%d", &r, &n);
43     for(int i = 0; i < n; i++) scanf("%lf", &w[i]);
44     for(int i = 0; i < (1<<n); i++) {
45       sum[i] = 0;
46       tree[i].clear();
47       for(int j = 0; j < n; j++)
48         if(i & (1 << j)) sum[i] += w[j];
49     }
50     int root = (1 << n) - 1;
51     memset(vis, 0, sizeof(vis));
52     dfs(root);
53     double ans = -1;
54     for(int i = 0; i < tree[root].size(); i++)
55       ans = max(ans, tree[root][i].L + tree[root][i].R);
56     printf("%.10lf\n", ans);
57   }
58   return 0;
59 }
时间: 2024-10-25 21:07:32

UVa1354 Mobile Computing (枚举二叉树)的相关文章

UvaLive 3403 Mobile Computing 枚举二叉树

题目链接:点击打开链接 题意: 给定房间宽度r和s个石头重量 设计一个尽量宽但宽度不超过房间宽度r的天平,使得能把所有石头放在天平上 (天平的一端要么挂一个石头,要么挂一个天平) 天平的平衡满足杠杆原理(两端重量的比值与两端距离悬挂天平点的距离成反比,每根天平杆长度为1) 输出最大的宽度(若不能把石头都挂上输出-1) 思路: 枚举计算每一个状态时的最大宽度. 若这个状态只有一个石头,那么得到的天平就认为是(0,0) (0,0)的意思是以天平支点为准,向左延展的长度和向右延展的长度 否则一定是由2

UVa 1354 Mobile Computing[暴力枚举]

**1354 Mobile Computing** There is a mysterious planet called Yaen, whose space is 2-dimensional. There are many beautiful stones on the planet, and the Yaen people love to collect them. They bring the stones back home and make nice mobile arts of th

1354 Mobile Computing(暴力、二进制枚举、简直无情)

翘了3节课来A这道题,最后还超时了,也是蛮拼的.. 没做出来主要一个方面就是不会一个二进制数子集的枚举 这里上一下代码: for(int S0 = S; S0; S0 = (S0 - 1) & S){ } 这里S0就是S的子集了~! 题目的思路就是枚举所有情况,注意记忆化[话说这题学到了不少] #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using n

UVA1354枚举二叉树

枚举二叉树的方式有很多,其中一种方式就是每次从一个集合中挑选两个点出来,一个做左子树,一个做右子树,直到集合中只剩下一个节点位置 那么问题就在于如何挑选?因为必须创建节点加入集合当中去. 我一开始的思路是使用vecoter,每挑选一个就删除一个,并把新创建的节点加入到vector中去. 但是这种方式是行不通的,因为当回溯的时候,vector不可能恢复原样.所以使用的方法只能是在数组的末尾添加,每挑选一个节点,就设置一次vis,当第cur次挑选的时候,挑选的范围是num_node + cur.这很

uva 1354 Mobile Computing ——yhx

1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 struct node 5 { 6 int fat,lson,rson; 7 double wei; 8 }tree[500]; 9 double w[10],lim,ans; 10 int n; 11 double max(double x,double y) 12 { 13 return x>y?x:y; 14 } 15 void calc_s

Uva 1354 Mobile Computing

题目链接 题意: 在一个宽为r 的房间里, 有s个砝码, 每个天平的一端要么挂砝码, 要么挂另一个天平, 并且每个天平要保持平衡. 求使得所有砝码都放在天平上, 且总宽度不超过房间宽度的最大值. 思路: 每个节点只能有两个子节点, 这是一棵二叉树的形式. 通过枚举二叉树的形态, 再枚举每一个叶子节点所放砝码, 最后再计算每个方案的宽度并计算答案. 每增加一个天平, 那么可以放砝码数 + 1. note: 坑在0的输出了, 用primtf("%.9lf\n", 0)输出来的是0  用0.

UVa 1354 天平难题 (枚举二叉树)

题意: 分析: 其实刚看到这题的时候觉得很难, 以至于结束了第七章然后去做了一遍第六章树的部分.现在再做这题觉得思路并不是太难,因为总共就只有六个结点,那么只要枚举二叉树然后算出天平然后再从叶子往上推就能得出这棵树的宽度.这题我觉得主要难点是如何去枚举二叉树,其实这就是回溯法的核心.先去dfs选这个作为结点的, 然后还原, 再做不选的dfs, 这样就能没有遗漏(但会有重复)地枚举二叉树了. 这题还有个细节是一个天平中,左子树的右长度可能会超过天平右臂 + 右子树的长度, 如下图 那么就不能单纯地

MITG2102 Mobile Computing (Section 51)

College of International Education (CIE)Associate Degree ProgrammeProject on Mobile Applications Development Course : MITG2102 Mobile Computing (Section 51)Year/Term : 2018-19, Semester 2Deadline : 2 May, 2019 (Thu) 17:30 onto MoodleCredit : 50% of t

CSE 535: Mobile Computing

CSE 535: Mobile ComputingAccelerometer Data GraphAssignment 2Purpose:Assignment 2 will be an extension of Assignment 1. In this assignment, you will be developing adatabase for a patient. There are 3 parts to complete for Assignment 2. The components