UVa 12166 Equilibrium Mobile

探讨如何通过最少次数的重量调整使不平衡的移动雕塑达到稳定状态。介绍了一种算法思路,利用节点深度信息转换节点值,从而找出需要更改的最小权重数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 A mobile is a type of kinetic sculpture constructed to take advantage of the principle of equilibrium. It consists of a number of rods, from which weighted objects or further rods hang. The objects hanging from the rods balance each other, so that the rods remain more or less horizontal. Each rod hangs from only one string, which gives it freedom to rotate about the string.

We consider mobiles where each rod is attached to its string exactly in the middle, as in the figure underneath. You are given such a configuration, but the weights on the ends are chosen incorrectly, so that the mobile is not in equilibrium. Since that's not aesthetically pleasing, you decide to change some of the weights.

What is the minimum number of weights that you must change in order to bring the mobile to equilibrium? You may substitute any weight by any (possibly non-integer) weight. For the mobile shown in the figure, equilibrium can be reached by changing the middle weight from 7 to 3, so only 1 weight needs to changed.

Input

On the first line one positive number: the number of testcases, at most 100. After that per testcase:
  • One line with the structure of the mobile, which is a recursively defined expression of the form:
      <expr> ::= <weight> | "[" <expr> "," <expr> "]"
    with <weight> a positive integer smaller than 109 indicating a weight and [<expr>,<expr>] indicating a rod with the two expressions at the ends of the rod. The total number of rods in the chain from a weight to the top of the mobile will be at most 16.

Output

Per testcase:
  • One line with the minimum number of weights that have to be changed.

Sample Input

3
[[3,7],6]
40
[[2,3],[4,5]]

Sample Output

1
0
3
The 2008 ACM Northwestern European Programming Contest


#include <iostream>
#include <string>
#include <cmath>
#include <vector>
#include <utility>
#include <map>
#include <cstdlib>
#include <cstdio>
using namespace std;
string str;

int main()
{
	int n;
	cin >> n;
	int count = 0;
	while(count < n)
	{
		// 读入每个情况
		cin >> str;
		// 记录当前节点的深度
		int now_depth = 0;
		int max_depth = 0;
		// 记录节点总个数
		int total_num = 0;
		// 设根节点的深度为0
		int i = 0;
		// 记录节点值和深度
		vector<pair<int,int> > val_array;
		// 处理字符串,记录节点值和深度
		while(i < str.length())
		{
			if(str[i] == '[')
			{
				now_depth++;
				if(max_depth < now_depth)
					max_depth = now_depth;
			}
			else if(str[i] == ']')
			{
				now_depth--;
			}
			else if(str[i] >= '0' && str[i] <= '9')
			{
				int j = i;
				while(j < str.length() && (str[j] >= '0' && str[j] <= '9'))
					j++;
				int x = atoi(str.substr(i, j-i).c_str());
				val_array.push_back(pair<int,int>(x, now_depth));
				total_num++;
				i = j-1;
			}
			i++;				
		}						
		// 算出所有节点在最深层的值
		// 得出节点在最深层值相同的最大个数
		map<double, int> my_map;
		int max_num = 0;
		for(int i = 0; i < val_array.size(); i++)
		{
			double this_num = 1.0* val_array[i].first / pow(2, max_depth-val_array[i].second);		
			if(my_map.find(this_num) == my_map.end())
			{
				my_map[this_num] = 1;
				if(max_num < 1)
					max_num = 1;
			}
			else
			{
				my_map[this_num]++;
				if(my_map[this_num] > max_num)
					max_num = my_map[this_num];
			}
		}
		
		printf("%d\n", total_num - max_num);
		count++;		
	}		
	return 0;
}


一道好题!这道题是自己做出来了,以下讲讲思考过程。
刚拿到题时感觉没太有头绪,后来发现一条性质:已知树的结构,给出树中任意一个节点的具体数值,那么整棵树的所有节点的值都可以据此算出来。

根据这条性质往下想,给出一个树的结构,树中节点的数值未知,设一个最深层的叶子节点的数值为x, 其他节点的值都是x的表达式。
并且是x的2的幂次倍,和深度有关。这样,就想出一个方法:得出每个节点的深度后,算出其在最深层叶子节点的值。这样取最深层叶子节点的值相同的节点最大个数,为不需要改动节点的个数,用总节点减去不需要改动节点的个数,就是答案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值