zoukankan      html  css  js  c++  java
  • BestCoder Round92

    题目链接:传送门 HDU 6015-6018

    解题报告:传送门

    HDU6015

    Skip the Class

     
     Accepts: 678
     
     Submissions: 1285
     Time Limit: 2000/1000 MS (Java/Others)
     
     Memory Limit: 65536/65536 K (Java/Others)
    问题描述
    终于又开学啦。呃喵最喜欢的就是开学了,因为这样她又可以愉快地翘课了(啊?)
    呃喵接下来有n节课程需要上(换句话说,可以翘。)
    每节课程有相应的课程类型与课程翘课价值。
    有一点需要注意的是,呃喵不可以翘同一类课程超过两次,就是如果这类课已经翘了两次,接下来就一定要上。
    问你在这个条件下,呃喵可以获得的最大翘课价值。
    输入描述
    第一行为一个整数T,代表数据组数。
    接下来,对于每组数据——
    第一行一个整数n,表示接下来需要依次上的课程数量,
    接下来有n行,每行包括一个仅由'a'~'z'构成的长度不超过10的字符串s与一个正整数v。
    其中字符串表示课程的类型,相同的字符串代表相同的课程。
    
    数据保证——
    1 <= T <= 1000
    对于每组数据,1 <= n <= 100,1 <= |s| <= 10, 1 <= v <= 1000
    输出描述
    对于每组数据,输出一行。
    该行有1个整数,表示呃喵可以获得的最大翘课价值。
    输入样例
    2
    5
    english 1
    english 2
    english 3
    math 10
    cook 100
    2
    a 1
    a 2
    输出样例
    115
    3

    题解:显然,对于每一种类型的课程,我们只会选择翘掉 翘课价值最大的前2节课。
    于是,最方便的做法,是使用map<string, int>first, second来实现。
    即:
    for(i = 1 ~ n)
    {
        scanf("%s%d", s, &v);
        gmax(second[s], v);
        if (second[s] > first[s])swap(second[s], first[s]);
    }
    然后把两个map中的权值全部加到sum中即可。

    代码一:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <map>
    #include <vector>
    #include <string>
    #include <iostream>
    using namespace std;
    map <string,vector<int> > a;
    int main()
    {
        int t,n,num,it;
        string c;
        scanf("%d",&t);
        while(t--)
        {
            a.clear();
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                cin>>c>>num;
                if(!a.count(c)) a[c]=vector<int>();
                if(a[c].size()<2)
                a[c].push_back(num);
                else
                {
                    if(a[c][0]<a[c][1]) swap(a[c][0],a[c][1]);
                    if(num>a[c][1]) a[c][1]=num;
                }
            }
            map<string,vector<int> >::iterator it;
            int sum=0;
            for(it=a.begin();it!=a.end();it++)
            {
                sum+=it->second[0];
                if(a[it->first].size()==2)
                sum+=it->second[1];
            }
            printf("%d
    ",sum);
        }
        return 0;
    }

    代码二:

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    int main()
    {
        map<string,int>first,second;
        int t,n,num;
        char c[15];
        scanf("%d",&t);
        while(t--)
        {
            first.clear();
            second.clear();
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%s%d",c,&num);
                second[c]=max(second[c],num);
                if(second[c]>first[c]) swap(first[c],second[c]);
            }
            int sum=0;
            map<string,int>:: iterator it;
            //这里的->second指的是map<key,value>中的value
            for(it=first.begin();it!=first.end();it++) sum+=it->second;
            for(it=second.begin();it!=second.end();it++) sum+=it->second;
            printf("%d
    ",sum);
        }
        return 0;
    }

    HDU6016

    Count the Sheep

     
     Accepts: 227
     
     Submissions: 805
     Time Limit: 3000/1500 MS (Java/Others)
     
     Memory Limit: 65536/65536 K (Java/Others)
    问题描述
    开学翘课固然快乐,然而也有让呃喵抓狂的事,那当然就是考试了!这可急坏了既要翘课又想要打BC还要准备考试的呃喵。
    呃喵为了准备考试没有时间刷题,想打BC又不想跌分,只得求助于BCround92的出题人snowy_smile,让他说点什么 ~~>_<~~。
    snowy_smile实在没有办法,但是又不好意思透题,只好告诉呃喵,当务之急是好好休息。
    "如果你按照下面这个办法睡着,那么第二天就绝对不会在BC的赛场上跌分——
    想象一片一望无际、广阔无边的青青草原,草原上住着一群羊,包括n只沉默的男羊和m只流泪的女羊,在男羊和女羊之间,存在k个朋友关系。
    现在你可以以任意一只羊为起点,顺着朋友关系数下去。如果能够连续数4只各不相同的羊,就能超过99%的数羊者,成功入睡。"
    呃喵听后十分震惊,但她还是听话地数下去,果然,数到第4只羊就睡着了,并一口气睡过了头,成功地错过了第二天的BestCoder,真的不会在BC的赛场上跌分啦!
    然而你,可就没有这么好的运气了,你既然看到了这第二题,自然一般已有提交,已经无法回头了。
    面对"不AC这题就可能跌分"窘境的你,需要说出,呃喵在睡前可能有多少种不同的数羊序列。
    即输出"A-B-C-D"这样序列的方案数,满足A-B、B-C、C-D是朋友关系且A、B、C、D各不相同。
    输入描述
    第一行输入数据组数T
    对于每组数据,第一行有三个整数n, m, k,表示n只男羊编号分别为1~n,m只女羊编号分别为1~m,并且存在k个朋友关系。
    接下来给出k行,每行给出两个数x y,表示第x只男羊和第y只女羊是朋友。
    
    数据保证——
    不会给出重复的朋友关系
    1 <= T <= 1000
    对于30%的数据,1 <= n, m, k <= 100
    对于99%的数据,1 <= n, m, k <= 1000
    对于100%的数据,1 <= n, m, k <= 100000
    输出描述
    对于每组数据,输出一行,该行包含一个整数,表示呃喵睡觉前可能数了哪4只羊的序列的方案数。
    输入样例
    (为了方便阅读,样例输入中数据组间中会额外添加一行空行)
    3
    2 2 4
    1 1
    1 2
    2 1
    2 2
    
    3 1 3
    1 1
    2 1
    3 1
    
    3 3 3
    1 1
    2 1
    2 2
    输出样例
    8
    0
    2
    Hint
    第一组样例:(b1-g1-b2-g2) (b1-g2-b2-g1) (b2-g1-b1-g2) (b2-g2-b1-g1) (g1-b1-g2-b2) (g1-b2-g2-b1) (g2-b1-g1-b2) (g2-b2-g1-b1) 共8种合法序列

    首先,因为朋友关系只能是在男羊和女羊之间的,所以这是一个二分图。
    然后,我们发现每个序列都满足一端为男羊,另外一端为女羊,于是我们可以按照"女羊A,男羊B,女羊C,男羊D"的方式计数,在最后使得答案*2就好。
    a[x]存是男羊x朋友的所有女羊,cnt[y]存女羊y拥有的男羊朋友数。于是:
    for (int x = 1; x <= n; ++x)                //枚举男羊B
    {
        LL onepoint = a[x].size() - 1;        //除去女羊C,女羊A的可能方案数为a[x].size() - 1
        for (auto y : a[x])                                //枚举女羊C,这两层for循环其实只枚举了k条边,复杂度为o(n+m+k)
        {
            ans += (cnt[y] - 1) * onepoint;    //显然除了男羊B,其他男羊都可以作为男羊D,计数为cnt[y] - 1
        }
    }最后ans * 2就是答案啦。
    PS:这题会爆int

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    const int N=1e5+10;
    typedef long long ll;
    vector <ll> a[N];
    ll cnt[N];
    int main()
    {
        int t,n,m,k,x,y;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&k);
            for(int i=1;i<=max(n,m);i++)
            {
                a[i].clear();
                cnt[i]=0;
            }
            memset(cnt,0,sizeof(cnt));
            for(int i=0;i<k;i++)
            {
                scanf("%d%d",&x,&y);
                a[x].push_back(y);
                cnt[y]++;
            }
            ll ans=0;
    //        for(int i=1;i<=n;i++)
    //        {
    //           for(int j=0;j<a[i].size();j++)
    //            printf("%d ",a[i][j]);
    //            puts("");
    //        }
            for(int i=1;i<=n;i++)
            {
                ll tmp=a[i].size()-1;
                vector <ll>::iterator it;
                for(it=a[i].begin();it!=a[i].end();it++)
                ans+=(cnt[*it]-1)*tmp;
                //for(int j=0;j<a[i].size();j++)
                //ans+=(cnt[a[i][j]]-1)*tmp;
            }
            printf("%lld
    ",ans*2);
        }
        return 0;
    }
    /*
    3
    2 6 4
    1 5
    1 6
    2 5
    2 6
    
    3 1 3
    1 1
    2 1
    3 1
    
    3 3 3
    1 1
    2 1
    2 2
    */
  • 相关阅读:
    OSI安全体系结构
    PHP 二维数组根据相同的值进行合并
    Java实现 LeetCode 17 电话号码的字母组合
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 14 最长公共前缀
  • 原文地址:https://www.cnblogs.com/Ritchie/p/6473408.html
Copyright © 2011-2022 走看看