题意:一个天平表达式:[A,B],其中A和B为一个数值或又一个天平表达式。每个天平表达式代表的天平所有长度相等,故如果需要平衡,则要求两边质量相等。题目则是给出了一个天平表达式,要求计算,在给出表达式的情况下,如果要求平横,则最少需要调整几个物体。
思路:假设有N个物体(砝码)在天平上,那么最多需要修改N-1个,因为最差的情况就是照着其中一个点不变,然后其它点都以它为基准,进行调平。
那么,可以这么想,遍历每一个砝码,并以它为基准,最少需要调解多少个?
因为一个天平中,上一层单个点的质量是下一层单个点质量的两倍,那么就可以算出最高层需要的质量为多少。比如第2层中的一个砝码质量为2,那么第一层的质量需要4;
比较每一个点,根据所在层数,计算即可发现如果一个点不变,最高层需要多少质量,最后观察同一质量被需要次数最多是多少。
/* UvaOJ 12166 Emerald Mon 27 Jul 2015 */ #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <string> #include <map> using namespace std; string expr; int needChange; map<long long, int> hashCount; // build the binary tree void BuildTree(string& s, int& start, int root, int layout) { long long tmp; if( s[start] != '[' ) { sscanf( &s[start], "%lld", &tmp ); if( !hashCount.count( tmp<<layout ) ) { hashCount[tmp<<layout] = 1; } else { hashCount[tmp<<layout] ++; } } else { BuildTree(s, ++start, root*2, layout+1); } for(; s[start]!=','; start++) { } start ++; if( s[start] != '[' ) { sscanf( &s[start], "%lld", &tmp ); if( !hashCount.count( tmp<<layout ) ) { hashCount[tmp<<layout] = 1; } else { hashCount[tmp<<layout] ++; } } else { BuildTree(s, ++start, root*2+1, layout+1); } } void Init() { hashCount.clear(); } void Solve() { needChange = 0; // can't be wasted, if it's forgotten, the case '40' may be wrong if(expr[0] != '[') { return ; } int pos = 1; BuildTree( expr, pos, 1, 1 ); map<long long, int> :: iterator it; int maxC = -1; int sum = 0; for( it = hashCount.begin(); it != hashCount.end(); it ++ ) { sum += it->second; maxC = maxC > it->second ? maxC : it->second; } needChange = sum - maxC; } void Print() { printf("%d ", needChange); } void Read() { cin >> expr; } void Work() { Init(); Read(); Solve(); Print(); } int main() { int T; cin >> T; while(T --) { Work(); } return 0; }