题解:P5013 水の斗牛

· · 题解

这个规则就不介绍了。自己看题。

这个我们可以按照每一个回合的顺序来模拟。

每一个回合分为如下几个部分。

  1. 发牌。
  2. 出牌。
  3. 比较和计分。

当然在模拟前,为了方便,我先写了一些结构体,并且重载运算符了这些结构体间的 ><

接下来我们可以按顺序来写。

我这里把每个回合的玩家用 _player 计为 p1p2p3

发牌

很明显,输入名字,二分找到 id,用字符串一个个输入卡牌,记录五张卡牌和最大卡牌。

出牌

我选择用五层循环枚举出牌方案,先尝试将前四张拼成炸弹,再尝试拼成牛,最后是无牛。用上文写的重载出来的运算符来比较不同牌组之间的大小这时就很方便了。

比较和计分

两两对比大小,再在底分 10 上进行加倍,然后赢得加,输的减。

其实代码也不算很难,作者 60 分钟就打完了。由于我的写法时间复杂度为 3 \times T \times 5^5+3\times T\times \log(n),而且使用结构体的时间常数比较大,得用 C++98 才能过。 :::success[code]

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
int id,T,n;
struct p
{
    int id,ans;
    string name;
}player[maxn];
bool cmpname(p A,p B)
{
    return A.name<B.name;
}
bool cmpid(p A,p B)
{
    return A.id<B.id;
}
int findd(string x)
{
    int l=0,r=n+1;
    while(l+1<r)
    {
        int mid=l+r>>1;
        if(player[mid].name>=x)r=mid;
        else l=mid;
    }
    return r;
}
struct poker
{
    int hs,num;
};
bool operator < (poker A,poker B)
{
    if(A.num!=B.num)return A.num<B.num;
    else return A.hs>B.hs;
}
bool operator > (poker A,poker B)
{
    if(A.num!=B.num)return A.num>B.num;
    else return A.hs<B.hs;
}
struct _player
{
    int id;
    poker a[6];
    int zd;//是否是炸弹 
    int tb;//是否有铁板
    int n;//几牛,!无牛设为0 ,牛牛设为 10 
    poker maxa;
};
bool operator < (_player A,_player B)
{
    if(A.zd || B.zd)return A.zd<B.zd;//有炸弹,比较炸弹大小,没有炸弹为 0,不影响计算 
    if(A.n==B.n)//牛数一样 
    {
        if(A.tb || B.tb)return A.tb<B.tb;//比较铁板 
        return A.maxa<B.maxa;//比较最大牌 
    }
    return A.n<B.n;
}
bool operator > (_player A,_player B)
{
    return B<A;
}

_player sc(_player A)
{
    _player maxp=A;
    for(int i1=1;i1<=5;i1++)//五 
    {
        for(int i2=1;i2<=5;i2++)//层 
        {
            if(i1==i2)continue;
            for(int i3=1;i3<=5;i3++)//大 
            {
                if(i1==i3 || i2==i3)continue;
                for(int i4=1;i4<=5;i4++)//循 
                {
                    if(i1==i4 || i2==i4 || i3==i4)continue;

                    for(int i5=1;i5<=5;i5++)//环 
                    {
                        if(i1==i2 || i1==i3 || i1==i4 || i1==i5 || i2==i3 || i2==i4 || i2==i5 || i3==i4 || i3==i5 || i4==i5)
                            continue;
                        poker p1=A.a[i1],p2=A.a[i2],p3=A.a[i3],p4=A.a[i4],p5=A.a[i5];
                        if(p1.num==p2.num && p2.num==p3.num && p3.num==p4.num)//炸弹 
                        {
                            A.zd=p1.num;
                            A.tb=0;
                            A.n=0;
                            if(A>maxp)maxp=A;
                            continue;
                        }
                        if(p1.num==p2.num && p2.num==p3.num)//铁板 
                        {
                            A.n=(p4.num+p5.num)%10;
                            if(A.n==0)A.n=10;
                            A.tb=p1.num;
                            A.zd=0;
                            if(A>maxp)maxp=A;
                            continue;
                        }
                        if((p1.num+p2.num+p3.num)%10==0)//牛 
                        {
                            A.n=(p4.num+p5.num)%10;
                            if(A.n==0)A.n=10;
                            A.tb=0;
                            A.zd=0;
                            if(A>maxp)maxp=A;
                            continue;
                        }
                        A.n=0,A.zd=0,A.tb=0;
                        if(A>maxp)maxp=A;//无牛 
                    }
                }
            }
        }
    }
    return maxp;
}
void ask(_player A,_player B)//比较并计分 
{
    if(A>B)
    {
        int s=10;
        if(A.zd)
        {
            s*=10;
        }
        else
        {
            if(A.n==10)s*=3;
            else if(A.n>=7)s*=2;
            if(A.tb)s*=2;
        }
        player[A.id].ans+=s;
        player[B.id].ans-=s;
        return;
    }
    int s=10;
    if(B.zd)
    {
        s*=10;
    }
    else
    {
        if(B.n==10)s*=3;
        else if(B.n>=7)s*=2;
        if(B.tb)s*=2;
    }
    player[B.id].ans+=s;
    player[A.id].ans-=s;
    return;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>id>>T>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>player[i].name;
        player[i].id=i;
    }
    sort(player+1,player+1+n,cmpname);
    while(T--)
    {
        _player p1,p2,p3;
        string p;
        string name;
        cin>>name;
        p1.id=findd(name);
        p1.n=p1.tb=p1.zd=0;
        for(int i=1;i<=5;i++)
        {
            cin>>p;
            if(p[0]=='a')p1.a[i].hs=1;
            if(p[0]=='b')p1.a[i].hs=2;
            if(p[0]=='c')p1.a[i].hs=3;
            if(p[0]=='d')p1.a[i].hs=4;
            if(p[1]=='A')p1.a[i].num=1;
            else p1.a[i].num=p[1]-'0';
            if(p.size()==3)p1.a[i].num=10;
            if(i==1)p1.maxa=p1.a[i];
            else if(p1.a[i]>p1.maxa)p1.maxa=p1.a[i];
        }
        cin>>name;
        p2.id=findd(name);
        p2.n=p2.tb=p2.zd=0;
        for(int i=1;i<=5;i++)
        {
            cin>>p;
            if(p[0]=='a')p2.a[i].hs=1;
            if(p[0]=='b')p2.a[i].hs=2;
            if(p[0]=='c')p2.a[i].hs=3;
            if(p[0]=='d')p2.a[i].hs=4;
            if(p[1]=='A')p2.a[i].num=1;
            else p2.a[i].num=p[1]-'0';
            if(p.size()==3)p2.a[i].num=10;
            if(i==1)p2.maxa=p2.a[i];
            else if(p2.a[i]>p2.maxa)p2.maxa=p2.a[i];
        }
        cin>>name;
        p3.id=findd(name);
        p3.n=p3.tb=p3.zd=0;
        for(int i=1;i<=5;i++)
        {
            cin>>p;
            if(p[0]=='a')p3.a[i].hs=1;
            if(p[0]=='b')p3.a[i].hs=2;
            if(p[0]=='c')p3.a[i].hs=3;
            if(p[0]=='d')p3.a[i].hs=4;
            if(p[1]=='A')p3.a[i].num=1;
            else p3.a[i].num=p[1]-'0';
            if(p.size()==3)p3.a[i].num=10;
            if(i==1)p3.maxa=p3.a[i];
            else if(p3.a[i]>p3.maxa)p3.maxa=p3.a[i];
        }
        p1=sc(p1),p2=sc(p2),p3=sc(p3);
        ask(p1,p2);
        ask(p1,p3);
        ask(p2,p3);
    }
    sort(player+1,player+1+n,cmpid);
    for(int i=1;i<=n;i++)
    {
        cout<<player[i].name<<' '<<player[i].ans;
        cout<<'\n';
    }
    return 0;
}

:::