UVA - 12166 Equilibrium Mobile 修改天平
题意
给一个深度不超过16的二叉树,代表一个天平。每根天平都悬挂在中间,每个秤砣的重量已知。至少修改多少个秤砣的重量才能让天平平衡?
分析
首先所有的子天平的支点都在天平的中间。这代表天平要想平衡,必须这个子天平两侧相等。还有就是修改了某个天平后父天平和祖宗天平都将因此受到影响。所以如果使用搜索先满足某个子天平然后调整父天平的做法难以下手。
因为想要找到最少修改的解决方案。所以我们要保留某种权重使得保留原来的秤砣数量最大。然而秤砣位于不同深度和不同的子天平。不一样的重量可能在整体而言却是达到平衡的解决方案。所以我们得想一种方法将重量转化成相对整体来说的一种权重。然后统计权重的个数。我们保留出现次数最多的权重就可以得到最少修改的解决方案了。计算公式如下:
Q(x)=x∗2n
Q
(
x
)
=
x
∗
2
n
其中n代表秤砣的深度。然后我们将所有秤砣利用该公式计算出权重之后,结果便是秤砣总个数-权重最大重复次数。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <set>
#include <map>
#include <set>
#include <stack>
#include <math.h>
#include <queue>
#include <string>
using namespace std;
const int maxn = 111;
const int INF = 111;
string s;
int cnt = 0, ans = 0;
map<long long , int> mp;
void init()
{
mp.clear();
cnt = 0;
ans = 0;
}
void solve(int cur, int b, int len)
{
if (s[b] == '[')
{
int p = 0;
for (int i = b + 1; i <= len; i++)
{
if (s[i] == '[') p++;
if (s[i] == ']') p--;
if (p == 0 && s[i] == ',')
{
solve(cur + 1, b + 1, i - 1);
solve(cur + 1, i + 1, len-1);
}
}
}
else {
long long w = 0;
for (int j = b; j <= len; j++)
{
w = w * 10 + s[j] - '0';
}
mp[w << cur] ++;
ans = max(ans, mp[w << cur]); //统计最大次数
cnt++;//统计秤砣个数
}
}
int main()
{
//freopen("cin.txt", "r", stdin);
//freopen("cout", "w", stdout);
int T;
scanf("%d", &T);
while (T--)
{
init();
cin >> s;
solve(0, 0, s.size() - 1);
cout << cnt - ans << endl;//结果
}
return 0;
}