这道题可以说是博主认为在树的DFS方面最为经典的一题了,思路巧妙细节满满啊。
输入一个树状天平,根据力矩相等原则判断是否平衡,所谓力矩相等,就是w1r1=w2r2,w为天平左右两端砝码的重量,r为距离。采用递归(先序)的方式输入:每个天平的格式为w1,r1,w2,r2。当w1或w2为零时,表示该砝码实际上是一个子天平,接下来会描述这个子天平,当w1=w2=0时,会先描述左子天平,再描述右子天平。
哦对了要先输入一个数字n,n表示天平的个数,还有就是,每两个输出数据之间要用一个空行隔开(是空行!!)博主最讨厌格式这种套路了qwq。。。
不用想先序递归肯定是用DFS做喽,由于数据是按照我们需要的顺序给出的,所以这个题的巧妙处理方式之一就是一边输入一边做题,而不是从前那样先将输入存储起来再做题。
思路大体是这样子,天平怎样才能平衡呢?,需满足以下三个条件
1.若左边是子天平,则左子天平需平衡,是砝码则忽略该条件。
2.若右边是子天平,则右子天平需平衡,是砝码则忽略该条件。
3.该天平需平衡,即w1*r1==w2*r2 。
当我们进行到子天平时,怎样判断这个子天平是否平衡呢?我们需要进去看看才行,当然,要把是否平衡作为结果带回哦。
分析到这里代码就很好写了:
#include<cstdio>
using namespace std;
bool dfs(int &w)
{
int w1,r1,w2,r2;
bool flag1=true,flag2=true;
scanf("%d%d%d%d",&w1,&r1,&w2,&r2); //边递归边输入,一般只有给出的数据是先序才能这么干
if(w1==0)
flag1=dfs(w1);
if(w2==0)
flag2=dfs(w2);
w=w1+w2;
return flag1&&flag2&&(w1*r1==w2*r2); //此处判断了上述的三个条件是否满足
}
int main()
{
int n;
int w;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
if(i!=0)
printf("\n"); //解决了垃圾的格式问题
if(dfs(w)) //w用来带回天平的重量
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
博主做这道题时还犯了一个错误,就是没给flag1和flag2赋初值,卡了半个多小时,最后看了答案还很倔觉得不用赋。。。后来明白了显然是要赋的,当天平一端为砝码是我们应默认这个砝码自身是平衡的,不赋这个值的话砝码的flag就成了随机值了,还真不是人家uva判的严。。。想想当时真是太菜了,不知道有没有和我犯一样错误的小伙伴呢?