码迷,mamicode.com
首页 > 其他好文 > 详细

UVa1354 Mobile Computing (枚举二叉树)

时间:2016-09-04 15:38:05      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

链接: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 }

 

UVa1354 Mobile Computing (枚举二叉树)

标签:

原文地址:http://www.cnblogs.com/XieWeida/p/5839227.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!