• uva1354 天平难题 解题报告


    uva1354 天平难题。主要有 回溯法,二叉树模拟。

    当然,这道题也有很多剪枝,但是这个用二叉树性质模拟的数组应该过了,这样写,这道题,完全就足够了。

    原题目链接:https://uva.onlinejudge.org/external/13/1354.pdf

    题目大意:

    就是首先给你一个房间的宽度r,之后有s个挂坠,第i个挂坠的重量是wi,设计一个尽量宽,但是不能宽过房间.的天平。当然会有好几组这样的数据。

    这些天平棍的长度都为1,天平棍要么挂 挂坠,要么就继续挂木棍设挂的木棍必须要让天平平衡,满足n*a==m*b。这就是个物理概念。

    其它东西,题目里写的很清楚。

    而这道题整体思想就是 1,枚举二叉树。2,计算宽度。

     

    枚举二叉树,很显然用到的是dfs+回溯。

    二叉树的模型,主要就用的是这个东西来枚举 like根==i子节点== i*2,i*2+1,这样的。

    从第二个点开始枚举。其中dfs(num,sit,use)

    num:代表这个节点编号,

    sit:现在这棵树中有多少位置可供填写。

    use:现在有use个挂件还可以用。

    PS:枚举的时候还要注意,每次进到一个新点的时候要判断父亲节点是不是天平棍,-1为棍,如果不是棍,就++,找下一个节点。

     

    计算宽度的时候,从最后一个点开始往前递推。设以这个节点为0,左边就是负长度,而右边就是正长度。这就很好的解释了其中

    l[i]=min(-L+l[x],R+l[y]);

    r[i]=max(-L+r[x],R+r[y]);

    这段代码的意思。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<string.h>
     4 using namespace std;
     5 double val[10],l[105],r[105],w[10],ans,room;
     6 int n,t[105],visit[105];
     7 int judge(int x)
     8 {
     9     memset(l,0,sizeof(l));
    10     memset(r,0,sizeof(r));
    11     memset(val,0,sizeof(val));
    12     for(int i=x;i;i--)
    13     {
    14         if(t[i]==-1){ //是天平棍,对它的子节点进行处理。
    15             int x=i*2,y=i*2+1;
    16             val[i]=val[y]+val[x];
    17             double L=val[y]/val[i];
    18             double R=val[x]/val[i];
    19             l[i]=min(-L+l[x],R+l[y]);
    20             r[i]=max(-L+r[x],R+r[y]);
    21         }
    22         else if (t[i])//或者是挂件。只计量挂件的重量就行了。
    23         {
    24             val[i]=w[t[i]];
    25         }
    26     }
    27     double a=r[1]-l[1];
    28     if(a-room<1e-5)ans=max(ans,a);
    29 }
    30 int DFS(int num,int sit,int use)
    31 {
    32     if(use==0){//所有的挂件都放完了,开始计算长度。
    33         judge(num-1);
    34         return 0;
    35     }
    36     if(t[num/2]!=-1){//父亲节点不是棍子,就不能往下放东西。
    37         DFS(num+1,sit,use);
    38     }
    39     else
    40     {
    41         if(use>sit){//挂件要比位置多,创位置。
    42             t[num]=-1;
    43             DFS(num+1,sit+1,use);
    44             t[num]=0;
    45         }
    46         if(sit==1&&use>1) return 0;
    47         for(int i=1;i<=n;i++)
    48         {
    49             if(!visit[i]){
    50                 visit[i]=1;
    51                 t[num]=i;
    52                 DFS(num+1,sit-1,use-1);//放挂件
    53                 visit[i]=0;
    54                 t[num]=0;
    55             }
    56         }
    57     }
    58 }
    59 int main()
    60 {
    61     int tot;
    62     scanf("%d",&tot);
    63     while(tot--)
    64     {
    65         scanf("%lf%d",&room,&n);
    66         memset(w,0,sizeof(w));
    67         memset(t,0,sizeof(t));
    68         memset(visit,0,sizeof(visit));
    69         for(int i=1;i<=n;i++)
    70         scanf("%lf",&w[i]);
    71         ans=-1;
    72         t[1]=-1;  //第一个根就是个棍。
    73         if(n==1){
    74             printf("%.10lf
    ",0.0);
    75         }
    76         else {
    77             DFS(2,2,n);//从节点2开始枚举。刚好就只有2个位置。
    78             if(ans==-1)printf("-1
    ");
    79             else printf("%.10lf
    ",ans);
    80         }
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    GIT 相关
    createFile
    值传递、指针传递、引用传递
    Sightseeing trip
    find the longest of the shortest
    Laurenty and Shop
    Dima and Lisa
    Marina and Vasya
    Kolya and Tanya
    Two Substrings
  • 原文地址:https://www.cnblogs.com/uncle-lu/p/5881045.html
Copyright © 2020-2023  润新知