网址如下:
Equilibrium Mobile - UVA 12166 - Virtual Judge (vjudge.net)
(第三方网站)
很骚的一题,让我对二叉树有了新的认知
简单来说就是给一个深度不超过16的二叉树,代表一个天平。每根杆都悬挂在中间,每个秤砣的重量已知。至少修改多少个秤砣的重量才能让天平平衡?
虽然给的树都是正整数,但是修改的重量可以是浮点数
天平的图片可以看网址里面的
代码如下:
#include<cstdio>
#include<list>
#include<map>
#include<cctype>
#include<cmath>
using namespace std;
const double EPS = 1e-6;
struct Node{
double v;
int depth;
Node(double v, int depth):v(v), depth(depth){}
};
int main(void)
{
int kase; scanf("%d", &kase); getchar();
while(kase--){
map<double, int> s;
list<Node> l;
int d{}, maxd{}; char c;
double ext{};
//输入
while((c = getchar()) != '\n'){
if(isdigit(c)) ext = ext * 10.0 + c - '0';
else{
if(ext){l.push_back(Node(ext, d)); ext = 0.0;}
if(c == '[') d++;
else if(c == ']') d--;
maxd = (maxd > d) ? maxd : d;
}
}
if(ext) l.push_back(Node(ext, d));
//处理
int maxn = 0;
for(auto it = l.begin(); it != l.end(); it++){
double val = it->v / pow(2.0, maxd - it->depth);
if(s.count(val)) s[val]++;
else s[val] = 1;
maxn = (maxn > s[val]) ? maxn : s[val];
}
//输出
printf("%d\n", l.size() - maxn);
}
return 0;
}
我刚开始一直在想:这不是要尽可能地使相邻层的重量相差一倍嘛,但是这要怎么搞?
如果一个一个试着改变的话,我估计大概率会超时,而且很麻烦
最后是想出了这个办法:
使二叉树不同深度的地方全部降到最低深度,因为天平两边的杆相同,所以是每下降一层就除2
公式:
double val = it->v / pow(2.0, maxd - it->depth);
//it指向当前结点,val是下降后的值,v是原来的值,maxd是最大深度,depth是当前结点的深度
然后就是求一堆数中,至少要修改多少个数的值,才能使所有数相等
这很简单
但是为什么会转化成这样?
因为对于下降过后的结点,如果更改这个下降后的结点的值一次,就是更改原来的结点的值一次
而对于同一个结点下降后虽然会分成多个结点,但是这些下降后的结点的值都是相等的,而改变所有这些下降后的结点(归属同一个原来的结点)的值,只需要改变一次原来的结点的值就行了,所以干脆把这些结点变成一个结点看待
具体实现看我代码