题意:给出房间宽度 r 和 s 个挂坠的重量 wi,设计一个尽量宽的天平,挂着所有挂坠。天平由一些长度为 1 的木棍组成,木棍的每一端要么挂一个挂坠,要么挂另外一个木棍。

这题卡了很久,看了很多大神的代码,终于把细节都搞懂了。

将挂坠所有可能的集合的重量算出来,再用二进制的方式枚举子集(左子树)和补集(右子树)构成二叉树,算出左右的宽度。

代码:

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;const int MAX = 6;struct Tree{double L, R;    //树的左边和右边的长度Tree():L(0), R(0){}
};double width, w[MAX], sum[1<<MAX];
int vis[1<<MAX];
vector<Tree> tree[1<<MAX];        //枚举出来的结点可以组合成多个树void dfs(int subset);        //枚举二叉树int main(){freopen("input.txt", "r", stdin);int T;cin >> T;while(T--){int s;scanf("%lf%d", &width, &s);for(int i=0; i<s; i++){scanf("%lf", &w[i]);}//初始化 memset(sum, 0, sizeof(sum));for(int i=1; i<(1<<s); i++){tree[i].clear();    //清空树int k = 1;for(int j=0; j<s; j++){    //算出当前集合所有结点的重量和if(k & i){sum[i] += w[j];}k = (k << 1);} }//进行枚举int root = (1<<s) - 1;memset(vis, 0, sizeof(vis));dfs(root);//得到最大的答案double ans = -1;for(int i=0; i<tree[root].size(); i++){ans = max(tree[root][i].L + tree[root][i].R, ans);} printf("%.10lf\n", ans);}} void dfs(int subset){if(vis[subset])return;vis[subset] = 1;bool hasChild = false;for(int left = ((subset-1) & subset); left > 0; left = ((left-1) & subset)){    //枚举集合 hasChild = true;int right = subset ^ left;        //left 的补集double l = sum[right] / sum[subset];    //左臂长度double r = sum[left] / sum[subset];        //右臂长度
        dfs(left);    dfs(right);        //把左右树的子树也枚举出来for(int i=0; i<tree[left].size(); i++){            //将枚举出的左右子树组合起来 for(int j=0; j<tree[right].size(); j++){Tree t;t.L = max(tree[left][i].L + l, tree[right][j].L - r);t.R = max(tree[right][j].R + r, tree[left][i].R - l);if(t.L + t.R < width){                    //如果满足条件,枚举结果加一
                    tree[subset].push_back(t); }}}}if(!hasChild){        //叶子结点的左右臂为零
        tree[subset].push_back(Tree());}}

转载于:https://www.cnblogs.com/lighter-blog/p/7216349.html

UVa 1354 天平难题 枚举二叉树相关推荐

  1. UVA1354天平难题 枚举二叉树

    题意:给出房间宽度r和s个挂坠的重量wi.设计一个尽量宽(但宽度不能超过房间宽度r)的天平,挂着所有挂坠.天平由一些长度为1的木棍组成.木棍的每一端要么挂一个挂坠,要么挂另一个木棍,设n和m分别是两端 ...

  2. LA3403天平难题(4个DFS)

    题意:      给出房间的宽度r和每个吊坠的重量wi,设计一个尽量宽但宽度不能超过房间宽度的天平,挂着所有挂坠,每个天平的一段要么挂这一个吊坠,要么挂着另一个天平,每个天平的总长度是1,细节我给出题 ...

  3. LA3403 天平难题

    题意:      给出房间的宽度r和每个吊坠的重量wi,设计一个尽量宽但宽度不能超过房间宽度的天平,挂着所有挂坠,每个天平的一段要么挂这一个吊坠,要么挂着另一个天平,每个天平的总长度是1,细节我给出题 ...

  4. UVA 1354 Mobile Computing

    题意: 给出房间的宽度r和s个挂坠的重量wi.设计一个尽量宽的天平(不能超过房间的宽度),挂着所有的挂坠.天平由长度为l的木棍组成,天平的一端不是挂坠就是另一个天平.必须满足n*a=m*b(l=a+b ...

  5. Uva 201 Squares (暴力 + 枚举)

    [题意] 给出  n*n 的 点 H 横向  V  纵向  (注意)  V  想 I,j  相反 问 边 为1 ,2 , 3 .... n 的  正方向有几个 [思路] n 很小 直接暴力 枚举 枚举 ...

  6. UVA 11134 Fabled Rook 枚举 multiset加速

    题意说的是给出一个长度为n的国际象棋的棋盘,然后给出n个车的可以放置的范围,范围是一个矩形,用左上和右下两对数来描述,问是否存在方式使得每个车都放在他自己的范围里面且相互不冲突 这里x方向和y方向是不 ...

  7. UVa 140 Bandwidth【枚举排列】

    题意:给出n个节点的图,和一个节点的排列,定义节点i的带宽b[i]为i和其相邻节点在排列中的最远的距离,所有的b[i]的最大值为这个图的带宽,给一个图,求出带宽最小的节点排列 看的紫书,紫书上说得很详 ...

  8. UVa 839 天平

    分析:这是DFS又一个经典题目,符合DFS的理念一路搜到底,再回头. 主要难度在于递归边界的书写上.(这个题的类型非常重要) 代码如下: #include <iostream> #incl ...

  9. AcWing479.加分二叉树(区间DP)题解

    加分二叉树 题目传送门 题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,-,n),其中数字1,2,3,-,n为节点编号. 每个节点都有一个分数(均为正整数),记第i个节点的分数为di ...

最新文章

  1. numpy.ravel() vs numpy.flatten()
  2. 怎么解决深入学习PHP的瓶颈
  3. 取模除法(逆元)(费马小定理)(线性求逆元)
  4. php把表单转为json保存,javascript – 使用jquery将表单数据保存到本地json文件中
  5. iText报表Java_(例)Java生成PDF报表 iText
  6. Docker 从入门到掉坑
  7. 补天五星计划范围更新,还有单个漏洞额外10000元现金奖励?!
  8. ElasticSearch 插件开发
  9. 信息技术是一把双刃剑,如何掌控好这柄剑?
  10. jumpserver开源堡垒机部署安装
  11. Linux下防止用户查看他人的进程-hidepid
  12. 福利卡巴斯基一年免费以及一些使用软件
  13. 什么是TTL?标准USB接口是TTL吗?RS232、RS422、RS485的区别?
  14. python闰月计算_Python实例讲解 -- 获取本地时间日期(日期计算)
  15. 开发人员如何在面试中介绍自己的项目经历
  16. Java 并发编程艺术 读书笔记
  17. AD那些事 切割板子形状,线的弧度转换
  18. 全国大学生软件测试大赛Web应用测试(五)Jmeter性能测试环境配置
  19. 以太网UDP数据协议
  20. 电力系统风力发电机组测控专用隔离变送器

热门文章

  1. java数组的调用_java中数组的应用及方法
  2. Tomcat开发Web项目基本结构
  3. 小学生计算机舞蹈,最近“泼水成画”很火?舞蹈生VS体育生,看到计算机:你是来添乱的?...
  4. 『设计模式』 又谈麦当劳的食品--组合模式(Composite)
  5. Markdown中希腊字母与代码对应表
  6. HDU-1857 畅通工程再续
  7. 数据结构-“栈”的基本操作
  8. 如何在64位Ubuntu16.04下安装java开发环境
  9. 如何使用eclipse进行嵌入式Linux的开发
  10. 升级到BigSur无法使用git和brew解决办法