UVa 1354 枚举子集 Mobile Computing

只要枚举左右两个子天平砝码的集合,我们就能算出左右两个悬挂点到根悬挂点的距离。

但是题中要求找尽量宽的天平但是不能超过房间的宽度,想不到要怎样记录结果。

参考别人代码,用了一个结构体的vector,保存每个集合合法方案的左右两端最长的距离。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <map>
 6 #include <cmath>
 7 #define MP make_pair
 8 #define Ft first
 9 #define Sd second
10 using namespace std;
11
12 typedef pair<double, double> PDD;
13
14 const int maxn = 10;
15 const int maxs = 1000;
16
17 vector<PDD> tree[maxs];
18
19 int n;
20 double r;
21 double a[maxn], w[maxs];
22 bool vis[maxs];
23
24 int bitcount(int x)
25 {
26     int ans = 0;
27     while(x) { ans += (x & 1); x >>= 1; }
28     return ans;
29 }
30
31 void dfs(int S)
32 {
33     if(vis[S]) return ;
34     vis[S] = true;
35     if(bitcount(S) == 1) { tree[S].push_back(MP(0, 0)); return ; }
36
37     PDD t = MP(0, 0);
38     for(int s1 = (S-1)&S; s1; s1 = (s1-1)&S)
39     {
40         int s2 = S ^ s1;
41         dfs(s1); dfs(s2);
42         double x1 = w[s2] / w[S], x2 = w[s1] / w[S];
43         for(int i = 0; i < tree[s1].size(); i++)
44             for(int j = 0; j < tree[s2].size(); j++)
45             {
46                 t.Ft = max(x1 + tree[s1][i].Ft, tree[s2][j].Ft - x2);
47                 t.Sd = max(x2 + tree[s2][j].Sd, tree[s1][i].Sd - x1);
48                 if(t.Ft + t.Sd < r) tree[S].push_back(t);
49             }
50     }
51 }
52
53 int main()
54 {
55     int T; scanf("%d", &T);
56     while(T--)
57     {
58         scanf("%lf%d", &r, &n);
59         for(int i = 0; i < n; i++) scanf("%lf", a + i);
60         int all = (1 << n) - 1;
61
62         for(int i = 0; i <= all; i++)
63         {
64             w[i] = 0;
65             tree[i].clear();
66             for(int j = 0; j < n; j++) if(i & (1 << j))
67                 w[i] += a[j];
68         }
69
70         memset(vis, false, sizeof(vis));
71         dfs(all);
72         double ans = -1;
73         for(int i = 0; i < tree[all].size(); i++) ans = max(ans, tree[all][i].Ft + tree[all][i].Sd);
74         if(ans < 0) puts("-1");
75         else printf("%.9f\n", ans);
76     }
77
78     return 0;
79 }

代码君

时间: 2024-11-09 15:38:01

UVa 1354 枚举子集 Mobile Computing的相关文章

UVA 1354 Mobile Computing(天平难题,枚举子集,递归,好题*)

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 /** 6 思路:在每一个根节点枚举左右子树 7 8 学习: 9 (1)枚举子集的方法 例如 枚举 s = 100101 的子集 10 for(int l = (s-1)&s , l > 0 ; l = (l-1) & s){ 11 int r = s ^ l; 12 (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

UVA 11825 - Hackers&amp;#39; Crackdown 状态压缩 dp 枚举子集

UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:11825 - Hackers' Crackdown 题意: 有一个由编号0~n-1的n台计算机组成的网络,一共同拥有n种服务,每台计算机上都执行着所有服务,对于每台计算机,你能够选择停止一项服务,这个行为会导致与这台计算机和与他相连的其它计算机上的这项服务都停止(原来已经停止的继续保持停止状态). 求最多能使多少个服务瘫痪(即没有不论什么一台计算机在执行这项服务). 分析: 题目说白了.就

【UVA】11464-Even Parity(二进制枚举子集)

枚举第一行的所有可能情况,之后根据上面行计算下面行(判断是否冲突),获得最终结果. 14058243 11464 Even Parity Accepted C++ 0.275 2014-08-18 05:14:15 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<stack> #inc

UVa 11825 - Hackers&#39; Crackdown DP, 枚举子集substa = (substa - 1)&amp;sta 难度: 2

题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2925 题意 n个节点,每个节点都有完全相同的n项服务. 每次可以选择一个节点,破坏该节点和相邻节点的某项服务. 问最多能完全破坏多少服务? 思路 如刘书, 直接枚举状态的子集 注意元素个数为k的集合有C^k_n个子集,那么枚举的时间复杂度为sum{c^k_n * 2^k} = 3^n

UVa 11025 The broken pedometer【枚举子集】

题意:给出一个矩阵,这个矩阵由n个数的二进制表示,p表示用p位二进制来表示的一个数 问最少用多少列就能将这n个数区分开 枚举子集,然后统计每一种子集用了多少列,维护一个最小值 b[i]==1代表的是选择了这一列 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack> 6 #include<vector&g

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为

UVa 1354 天平难题

首先呈现刘汝佳的高级代码 // UVa1354 Mobile Computing // Rujia Liu #include<cstdio> #include<cstring> #include<vector> using namespace std; struct Tree { double L, R; // distance from the root to the leftmost/rightmost point Tree():L(0),R(0) {} }; co

11825 - Hackers&#39; Crackdown 状态压缩 dp 枚举子集

11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:11825 - Hackers' Crackdown 题意: 有一个由编号0~n-1的n台计算机组成的网络,一共有n种服务,每台计算机上都运行着全部服务,对于每台计算机,你可以选择停止一项服务,这个行为会导致与这台计算机和与他相连的其他计算机上的这项服务都停止(原来已经停止的继续保持停止状态).求最多能使多少个服务瘫痪(即没有任何一台计算机在运行这项服务). 分析: 题目说白了,就是: 把n个集合p