您的位置:首页 > 其它

Uva 12166 严格平衡树

2015-11-14 17:24 375 查看
原题

一开始想得太简单, 直接读数据建立树, 然后像堆调整那样一个个结点检查并向上调整子节点的重量, 后来写到一半发现这样不可行, 需要处理的情况太多, 这样模拟的过程太繁琐了..

于是可耻地google了答案——原来这棵树每层的结点值都是满足一定规律的,在同一层上的结点值必须相等, 而且上层的值是下一层的节点值的两倍。

认识到这个规律后,还是需要做一点巧妙的处理(方法来自这里 ) :

由于只要选择一个叶节点作为标准就可以确定一棵树的总重量,

因此遍历每个叶节点, 确定以其作为标准时树的总重量,

那么最多叶节点对应的那个总重量就是树应该取的最终总重量 M,

用总的叶结点数减去M所对应的叶节点数即可得到需要改变的叶节点数.

还有一个需要注意的地方就是由于结点的值正好压了int的范围, 所以树的总重量肯定有可能超过int, 因此要用 long long 来存储树的总重量

以下为模仿答案写的代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <list>
#include <cassert>
#include <iomanip>

#pragma warning(disable:4996) //关掉4996警告

/*
Uva 439
关键 :  1. 事先找出规律!!!
2. 技巧 : 由于只要选择一个叶节点作为标准就可以确定一棵树的总重量,
因此遍历每个叶节点, 确定以其作为标准时树的总重量, 那么
最多叶节点对应的那个总重量就是树应该取的最终总重量 M,
用总的叶结点数减去M所对应的叶节点数即可得到需要改变的叶节点数
*/

using namespace std;

int Leaves;

string input;
int ptr;

map<long long, int> WeightNum;      // 记录树的某个总重量所对应的标准结点数

void Build(int Depth) {
char ch;
ch = input[ptr++];
if ( ch == '[' ) {
Build(Depth+1);
ch = input[ptr++];          // 读 ','
Build(Depth+1);
ch = input[ptr++];          // 读 ']'
}else {                         // 找到一个叶节点
long long sum = 0;
do {
sum = sum * 10 + ch - '0';
ch = input[ptr++];
} while ( ptr < input.size() && ch != ',' && ch != ']' );
ptr--;
WeightNum[sum << Depth]++;
Leaves++;
}
return;
}

int main( ) {
//freopen("input.txt", "r", stdin);
int N;
cin >> N;
for ( int i = 0; i < N; i++ ) {
WeightNum.clear( );
cin >> input;
Leaves = ptr = 0;
Build(0);
int mostNum = 0;
for ( auto it = WeightNum.begin( ); it != WeightNum.end(); it++ ) {
mostNum = max(mostNum, it->second);
}
cout <
a0f9
;< Leaves - mostNum << endl;
}

//system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: