UVA 12166 dfs+Map库的巧用

题意

给一个天平,每次可以修改天平左边或者右边的重量,想让这个天平能够所有天平都能够平衡,求最少需要修改的次数。


思路

最开始拿到这个题,完全没有头绪。

之后想到,如果固定一个砝码,那么就能够求出其余的所有砝码是不是需要修改了。

但是如果暴力模拟每一个砝码,则时间复杂度会超

于是又没有思绪了

再一想,这是一个二叉树,如果平衡了,那么只要知道一个砝码的重量,和砝码的深度,就能够知道整个天平的重量。

那么 ,直接过一遍每一个砝码,计算其天平重量,假如有M个砝码, 总重量为K的数量最多,为N个,那么,只需要修改M-K个砝码,便能够使所有都能够平衡了。


思路想到了

可是实现起来,好像不是那么的好编程。

主要是记录天平总重量,如果开一个vector ,每次遍历一遍,如果有则在那个数字上++,没有就添加到末尾,但是这样,在极限条件下也会超时的

于是编程又搁置了, 除非能够找到一个Lg(n)的查询速度的容器,后来想到Map就是lg(N)的查询,于是查了一下Map,这个题基本解决。

(有些数据结构也能实现这个功能,比如说之前数据结构课上老师讲的那个排序树。但是这毕竟是竞赛,如果能套用现有的容器,何乐而不为)

map的操作自行查阅

wa1

 记录数字记录错误

for(i = x; s[i]<='9'&&s[i]>='0';i++){
            t=t*k+s[i]-'0';
            k++;
}
错误低级得汗颜。 


AC

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <sstream>
#include <string>
#define maxn 23
#define inf 0x3f3f3f3f3f
using namespace std;
map <long long,int> q;
string s;
int sum;
void dfs(int x ,int d , int n){ //d为深度
    if(x>n)
        return;
    if(s[x]=='[')    //如果有[ d+1 继续搜索
        dfs(x+1,d+1,n); 
    else if(s[x]==',')
        dfs(x+1,d,n);
    else if(s[x]==']') //如果有] d-1 继续搜索
        dfs(x+1,d-1,n);
    else{
        int k=0;
        long long t=0;
        int i=0;
        for(i = x; s[i]<='9'&&s[i]>='0';i++){
            t=t*10+s[i]-'0';
        }
        sum++;
        q[t<<d]++;
        dfs(i,d,n);
    }
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        cin>>s;
        q.clear();
        sum=0;
        dfs(0,0,s.size()-1);
        int maxx=0;
        for(map <long long,int>::iterator it=q.begin();it!=q.end();++it){
            maxx=max(it->second,maxx);
        }
        printf("%d\n",sum-maxx);
    }
}
70ms

附上一个看不懂的代码

#include <bits/stdc++.h>  
using namespace std;  
  
int cur = 0;  
char str[1024000];  
map<long long, int> cnt;  
  
void DFS(int dep)  
{  
    if(isdigit(str[cur])){  
        long long a = 0;  
        while(isdigit(str[cur]))  
            a = a * 10 + str[cur++] - '0';  
        cnt[a<<dep]++;  
    }  
    else{  
        cur++; DFS(dep + 1);  
        cur++; DFS(dep + 1);  
        cur++;  
    }  
}  
  
int main()  
{  
    ios::sync_with_stdio(false);  
    int T; cin >> T; cin.get();  
    while(cur = 0, cnt.clear(), T--) {  
        cin >> str; DFS(0);  
        int mx = INT_MIN, sum = 0;  
        for(map<long long, int>::iterator it = cnt.begin(); it != cnt.end(); it++)  
            sum += it->second, mx = max(mx, it->second);  
        cout << sum - mx << endl;  
    }  
    return 0;  
}  

短得可怕,而且时间还特别快 20ms 以后有机会再来读这段代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值