UVA - 12166 Equilibrium Mobile

/*
题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3318


要点:
我觉得,这题主要是考察思维,而不是考察技巧
当然,还是有一点点技巧的,就是不用这个就会有些麻烦,比如map 的巧妙应用,就算是一个技巧


其实这题的思路也比较巧,就是对每个叶子结点,按照其深度,来推出如果以该叶子结点为基准,整棵树的质量


然后便能统计出每种总重量,各由多少个叶子结点推出,我们选最多的那个总重量,来保证需要修改的叶子最少


本题的巧妙之处就在于,只要以深度为depth(depth从0开始)重量为w的砝码为基准,那么就能求出整个天平的总重量,即w*2^(depth),在代码中可以简洁地表示为w<<depth。这样,我们只用统计每个可能的总重量对应了多少不需要改动的砝码,设一共有sum个砝码,总重量为sumw的天平对应的砝码个数是base[sumw],那么最终答案就是sum-max{base[i]}(i为所有可能的天平总重量)


查阅题解:
http://m.blog.csdn.net/hao_zong_yin/article/details/73028817
http://blog.csdn.net/u013555159/article/details/51356003
http://blog.csdn.net/crazysillynerd/article/details/43876123
http://www.bubuko.com/infodetail-714729.html

*/


#include <iostream>
#include <string>
#include <map>
#include <cctype>
#define rep(i, n) for (int i = 0; i < (n); i++)
typedef long long ll;
using namespace std;

int main()
{
	string s;
	map<ll, int> m;
	map<ll, int>::iterator it;
	
	int t;
	cin >> t;
	while (t--)
	{
		cin >> s;
		m.clear();
		
		int depth = 0, leaves = 0, sw_max = 0; // 分别为 当前深度、当前已找到的叶子数,以及 same wight _max,表示叶子重量出现的最多次数,我们取这个最多次数,把与之不同的进行修改,最后得到的就是最小修改次数
		rep(i, (int)s.size())
		{
			if (s[i] == '[') depth++;
			else if (s[i] == ']') depth--;
			else if (isdigit(s[i]))
			{
				leaves++;
				ll weight = 0;
				while (isdigit(s[i]))
				{
					weight = weight * 10 + s[i++] - '0';
				}
				weight <<= depth;
				m[weight]++;
				i--;
			}
		}
		for (it = m.begin(); it != m.end(); it++)
		sw_max = max(sw_max, it->second);
		cout << leaves - sw_max << endl;
	}
	return 0;
}


/*
  而贴出的其他题解链接,基本上都是用bfs的思路,也即:
  
  在每次出现逗号,且深度相对参数为0时(注意,这个地方有点奇妙,深度不是真正为0,而只是相对参数为0),将树分为左子树和右子树
  
  然后再对左右子树按照这样的思路来递归,直到这个参数表示的范围内,找不到任何 "[",或是"]",或是"," 
  此时就说明,我们已经把该参数范围里的所有特殊符号剔除,剩下的范围可以表示一个叶子,我们就可以求叶子的重量,再结合其深度,推出根节点位置的重量
  
  其他的思路,与上一种思路基本一致
*/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值