zoukankan      html  css  js  c++  java
  • Uva



    刚开始想用结论:

    若最终天平平衡,则在同一个深度的所有结点,无论它的祖先结点是什么,重量都应该相同。并且上一层的重量应该是下一层的2倍。证明其实是显然的。。之后只需要把所有的结点分块,然后取结点最多的块,其余的结点都要修改,就是答案。

    但是代码并不是很简洁,后来参考别人的做法,知道可以反过来想:

    要使得改动的数量最少,那么就至少有一个秤砣不变,然后以这个秤砣为基准来调整整个天平。天平的结构是二叉树,那么由此我们可以得出,如果以深度为d重量为w的秤砣为基准,那么整个天平的重量就是w * pow(2, d),即w << d。
    当然,可能会有一些秤砣算出的以各自为基准的天平总重量相同,设天平总重量为sumw,那么这些秤砣的数量就表示了如果使天平的总重量为sumw需要使多少个秤砣保持不变。
    基于上面的想法,就可以得到算法了。求出所有可能的sumw值以及其对应的秤砣数量,然后在这些sumw值中找到保持不变的秤砣数量中的最大值,设为maxn,设秤砣总数量为sum。那么sum - maxn即为所求。
    为了求出sumw对应的秤砣数量,这里用到了STL里的map结构,设为base,那么base[x]表示使天平的重量为x时保持不变的秤砣的数量。在建树时,每当扫描到叶子结点,即秤砣时,算出对应的sumw值,然后另base[sumw]自增1,这样所有的叶子节点都扫完之后,所有可能的sumw值也就算完了。接下来就只需要遍历一遍,找出最大值即可了。


    AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cctype>
    #include <cstring>
    #include <string>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <bitset> 
    #include <cassert> 
    #include <cmath>
    
    using namespace std;
    
    string line;
    map<long long, int> base;
    int sum;
    
    // 从深度depth开始,从line的第s个开始,重点为第e个
    void dfs(int depth, int s, int e)
    {
    	if (line[s] == '[') {
    		int p = 0;
    		for (int i = s + 1; i != e; i++) {
    			// 下面两个if是为了找到左子树
    			if (line[i] == '[') {
    				p++;
    			}
    			if (line[i] == ']') {
    				p--;
    			}
    			if (p == 0 && line[i] == ',') {
    				dfs(depth + 1, s + 1, i - 1); // dfs左子树
    				dfs(depth + 1, i + 1, e - 1); // dfs右子树
    			}
    		}
    	}
    	else {
    		long long w = 0;
    		for (int i = s; i <= e; i++) {
    			w = w * 10 + line[i] - '0';
    		}
    		sum++;
    		// 重量为w的秤砣为基准,整个天平的重量就是w * pow(2,depth),也就是w << depth
    		base[w << depth]++;
    	}
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	int T;
    	cin >> T;
    	while (T--) {
    		cin >> line; 
    		base.clear();
    		sum = 0;
    		dfs(0, 0, line.size() - 1);
    
    		int maxn = 0;
    		
    		for (map<long long, int>::iterator it = base.begin(); it != base.end(); it++) {
    			maxn = max(maxn, it->second);
    		}
    		cout << sum - maxn << endl;
    	}
    
    	return 0;
    }


  • 相关阅读:
    Android中Activity之间通信
    vs2017 2019 下载更新慢的解决方法
    c# 判断某个类是否实现某个接口
    mvc api 关于 post 跟get 请求的一些想法[FromUri] 跟[FromBody] 同一个控制器如何实现共存
    vs2017 mvc 自定义路由规则 出现 404.0 错误代码 0x80070002
    C# winform 发布的时候没有app.config去哪儿了?
    安装c#服务
    Type.GetType反射的对象创建Activator.CreateInstance
    c# 谷歌动态口令对接
    asp.net mvc 异步控制器
  • 原文地址:https://www.cnblogs.com/zhangyaoqi/p/4591539.html
Copyright © 2011-2022 走看看