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

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

时间:2016-05-07 14:55:45      阅读:305      评论:0      收藏:0      [点我收藏+]

标签:

 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)思考:如何表示 左边距离  右边距离 。 该点的左臂/右臂长度由子集决定:-sumw[r]/(sumw[l] + sumw[r]) + node[l][i].l
13         sumw[i] :表示子集i 的重量
14         node[i].l : 表示子集 i 的左臂长度
15             左臂+左子天平的左臂 与 右子天平的左臂-右臂  谁更小
16             右臂+右子天平的右臂 与 左子天平的右臂-左臂  谁更大
17 */
18 
19 
20 struct Node{
21     double l,r;  //存放该点的子天平   最左延伸点,最右延伸点
22     Node(){}
23     Node(double ll,double rr):l(ll),r(rr){}
24 };
25 int n;
26 double r,w[12],ans,sumw[1<<6];
27 int vis[1<<6];
28 vector<Node> node[1<<6];
29 int bitcount(int x){
30     if(!x) return 0;
31     return bitcount(x>>1) + (x&1);
32 }
33 void dfs(int s){
34     if(vis[s])  return ;
35     vis[s] = true;
36     if(bitcount(s) == 1){
37         node[s].push_back(Node{0,0});
38         return ;
39     }
40     for(int l = (s-1)&s ; l > 0 ; l = (l-1) & s){
41         int r = s ^ l;
42         dfs(l); dfs(r);          // 一个根节点 的 两个子集的所有方案.  node[l].size() 左边方案数 node[r].size() 右边方案数
43         for(int i = 0 ; i < node[l].size() ; i ++){
44             for(int j = 0 ; j < node[r].size() ; j ++){
45                 double ll = min(-sumw[r] / (sumw[l] + sumw[r]) + node[l][i].l, sumw[l] / (sumw[l] + sumw[r]) + node[r][j].l);
46                 double rr = max(sumw[l] / (sumw[l] + sumw[r]) + node[r][j].r, -sumw[r] / (sumw[l] + sumw[r]) + node[l][i].r);
47                 node[s].push_back(Node(ll, rr));
48             }
49         }
50     }
51 }
52 
53 void solve(){
54     memset(vis,0,sizeof(vis));
55     memset(node,0,sizeof(node));
56     ans = -1;
57     int s = (1<<n) - 1;
58     dfs(s);
59     for(int i = 0 ; i < node[s].size() ; i ++){
60         if(node[s][i].r - node[s][i].l < r && node[s][i].r - node[s][i].l > ans){
61             ans = node[s][i].r - node[s][i].l;
62         }
63     }
64     if (ans == -1) printf("-1\n");
65     else printf("%.10lf\n", ans);
66 }
67 
68 int main(){
69     int T;
70     scanf("%d",&T);
71     while(T--){
72         scanf("%lf%d",&r,&n);
73         for(int i = 0 ; i < n ; i ++) scanf("%lf",&w[i]);
74         for(int i = 0 ; i < (1 << n ) ; i ++){
75             sumw[i] = 0;
76             for(int j = 0 ; j < n ; j ++){
77                 if(i & (1 << j)) sumw[i] += w[j];
78             }
79         }
80         solve();
81     }
82     return 0;
83 }

 

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

标签:

原文地址:http://www.cnblogs.com/zstu-jack/p/5468263.html

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