BestCoder Round #92 A+B

很久没打BC了,昨天一场又掉了几十分,掉掉涨涨,就是这样,下面来看一下前两题的题解吧(主要是为了记录一下自己的状态,逼自己努力,重新找回原来的状态)。

直接用官方题解+自己的想法+代码

A.题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6015

题目大意:n门课,每门课对应有一个价值,并且每门课最多翘两次,求翘课的最大价值。

分析:对于没门课程,我们只会选择翘课价值最大的前两节课,求出最大价值总和即可,先排序,用map实现。

Code:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<map>
#include<stack>
using namespace std;
#define mann 100010
#define INF 0x3f3f3f3f
#define Max 1e14+10
typedef long long LL;
struct node
{
    string s;
    int x;
} c[105];
bool cmp(node a,node b)
{
    if(a.s+b.s==b.s+a.s)
        return a.x>b.x;
    else
        return a.s+b.s<b.s+a.s;
}
map<string,int>mp;
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        mp.clear();
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            cin>>c[i].s>>c[i].x;
        sort(c,c+n,cmp);
        int sum=0;
        for(int i=0;i<n;i++)
        {
            if(mp[c[i].s]<2)
            sum+=c[i].x;
            mp[c[i].s]++;
        }
        printf("%d\n",sum);
    }
}
B.题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6016

题目大意:以任意一只羊为起点,顺着朋友关系数下去。如果能够连续数4只各不相同的羊,就能超过99%的数羊者,成功入睡。

即输出"A-B-C-D"这样序列的方案数,满足A-B、B-C、C-D是朋友关系且A、B、C、D各不相同。问有多少种不同的数羊序列。

分析:这看上去是一个二分图,但和二分图并没有什么关系,我们发现每个序列都满足一端为男羊,另外一端为女羊,于是我们可以按照"女羊A,男羊B,女羊C,男羊D"的方式计数,在最后使得答案*2就好。

刚开始看到题目,一脸懵比,不知道怎么去搞,后来想着用矩阵去存关系,以每个点为直角顶点的等腰直角三角形就是一种数羊序列,但数据范围比较大,这样写肯定过不了终判,然后就不知道怎么搞了。

看了题解后,忽然明白,我们可以枚举中间那条边(A-B-C-D,即B-C),那么结果就是(a[x]-1)*(b[y]-1),a[x]与男羊x有关系的女羊数目,b[y]代表与女样y有关系的男羊数目,那么以x-y为中间关系的数羊序列就有ans+=(a[x]-1)*(b[y]-1)种,总的结果可以反过来数,就是ans*2; PS: 对于边数很大的完全图在内的某些图时,计数会爆int。对于不算复杂度的暴力做法也会收获tle。

Code:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<map>
#include<stack>
using namespace std;
#define mann 100010
#define INF 0x3f3f3f3f
#define Max 1e14+10
typedef long long LL;
LL x[mann],y[mann],a[mann],b[mann];
int main()
{
    int t,n,m,k;
    scanf("%d",&t);
    while(t--)
    {
        memset(b,0,sizeof(b));
        memset(a,0,sizeof(a));
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0; i<k; i++)
        {
            scanf("%lld%lld",&x[i],&y[i]);
            a[x[i]]++;//与男羊x[i]有关系的女羊个数
            b[y[i]]++;//与女羊y[i]有关系的男羊个数
        }
        LL ans=0;
        for(int i=0; i<k; i++)//只枚举有关系的边,否则全部枚举会TLE
        {
            if(a[x[i]]>1&&b[y[i]]>1)
            ans+=(a[x[i]]-1)*(b[y[i]]-1);
        }
        printf("%lld\n",ans*2);
    }
}

BC主要还是考思路的,好的逻辑思维方式获益终身。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值