Uva 12166 严格平衡树

来源:互联网 发布:linux3.0内核源码分析 编辑:程序博客网 时间:2024/06/05 17:42

原题

一开始想得太简单, 直接读数据建立树, 然后像堆调整那样一个个结点检查并向上调整子节点的重量, 后来写到一半发现这样不可行, 需要处理的情况太多, 这样模拟的过程太繁琐了..
于是可耻地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 << Leaves - mostNum << endl;    }    //system("pause");    return 0;}
0 0
原创粉丝点击