zoukankan      html  css  js  c++  java
  • UVa 1354 天平难题 (枚举二叉树)

    题意:

    分析:

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

    这题还有个细节是一个天平中,左子树的右长度可能会超过天平右臂 + 右子树的长度, 如下图

    那么就不能单纯地看右臂+右子树的长度了, 要取一个最大值作为这个天平的最右, 反过来的左边也是一样的。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 using namespace std;
     5 struct Tree{
     6     double L, R;
     7     Tree(int _L = 0, int _R = 0):L(_L), R(_R){}
     8 };
     9 Tree tree[1<<6];
    10 int w[1<<6], vis[1<<6];
    11 
    12 int n, ind;
    13 double room, maxw;
    14 
    15 int dfs(int dep){
    16     if(dep == n - 1){// 递归边界
    17         if(tree[ind].L + tree[ind].R <= room)
    18             maxw = max(maxw, tree[ind].L + tree[ind].R);
    19     }
    20     for(int i = 1; i <= ind; i++){
    21         if(!vis[i]){
    22             for(int j = 1; j <= ind; j++){
    23                 if(i != j && !vis[j]){
    24 
    25                     vis[i] = vis[j] = 1;//建树
    26                     w[++ind] = w[i] + w[j];
    27 
    28                     int wl = w[i], wr = w[j];
    29                     //   a  |  b
    30                     //  ----------
    31                     //  |        |
    32                     //  wl      wr
    33 
    34                     double a = (double)wr/(wl + wr);
    35                     double b = 1.0 - a;
    36 
    37                     tree[ind].R = max(b + tree[j].R, tree[i].R - a);//比较着取最大值,
    38                     tree[ind].L = max(a + tree[i].L, tree[j].L - b);
    39 
    40                     dfs(dep + 1);
    41 
    42                     vis[i] = vis[j] = vis[ind] = 0;//还原
    43                     tree[ind].R =  tree[ind].L = 0;
    44                     --ind;
    45                 }
    46             }
    47         }
    48     }
    49 }
    50 int main(){
    51     int T;
    52     scanf("%d", &T);
    53     while(T--){
    54         memset(tree,0,sizeof(tree));
    55         ind = 0;//秤砣数组下标
    56         scanf("%lf", &room);
    57         scanf("%d", &n);
    58         for(int i = 1; i <= n;i++){
    59             scanf("%d", &w[i]);
    60             ind++;
    61         }
    62         maxw = -1;
    63         memset(vis,0,sizeof(vis));
    64         dfs(0);
    65         if(maxw == -1)
    66             printf("-1
    ");
    67         else
    68         printf("%.16f
    ", maxw);
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    java-Date、String、Calendar转化
    java -日期
    eclipse安装ADT
    Echarts-axislabel文字过长导致显示不全或重叠
    Echarts-柱状图柱图宽度设置
    Echarts-画叠加柱状图,双折线图
    Echarts-画堆积柱状图,折线图
    Echarts-画柱状,折线图
    windows系统激活-使用微软官方公布的kms client setup key安装或安装后使用slmgr导入
    Office 2013 Pro Plus Vol激活
  • 原文地址:https://www.cnblogs.com/Jadon97/p/7469742.html
Copyright © 2011-2022 走看看