UVA - 12166 Equilibrium Mobile 修改天平
題意
給一個深度不超過16的二叉樹,代表一個天平。每根天平都懸掛在中間,每個秤砣的重量已知。至少修改多少個秤砣的重量才能讓天平平衡?
分析
首先所有的子天平的支點都在天平的中間。這代表天平要想平衡,必須這個子天平兩側相等。還有就是修改了某個天平後父天平和祖宗天平都將因此受到影響。所以如果使用搜索先滿足某個子天平然後調整父天平的做法難以下手。
因爲想要找到最少修改的解決方案。所以我們要保留某種權重使得保留原來的秤砣數量最大。然而秤砣位於不同深度和不同的子天平。不一樣的重量可能在整體而言卻是達到平衡的解決方案。所以我們得想一種方法將重量轉化成相對整體來說的一種權重。然後統計權重的個數。我們保留出現次數最多的權重就可以得到最少修改的解決方案了。計算公式如下:
其中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;
}