题解:P5013 水の斗牛
这个规则就不介绍了。自己看题。
这个我们可以按照每一个回合的顺序来模拟。
每一个回合分为如下几个部分。
- 发牌。
- 出牌。
- 比较和计分。
当然在模拟前,为了方便,我先写了一些结构体,并且重载运算符了这些结构体间的
-
结构体
p,这个结构体用来存玩家的名字、计分、编号,和输入的顺序,因为作者太菜了,不会用map,所以要排序后用二分。如果你选择用map,你可以不管。 -
结构体
poker,这个结构体里有两个int,分别是一张牌的花色和点数。poker之间比较非常明显,先比较点数,相同则比较花色。 -
结构体
_player,记录了一个玩家的编号、手牌和出牌的情况,出牌情况分为:zd是否有炸弹,没有为0 ,否则为炸弹的点数。tb是否有铁板,没有为0 ,否则为铁板的点数。n是几牛,无牛为0 ,牛牛为10 ,否则为牛数。maxa是最大卡牌,类型为poker。id即编号。
_player之间要先比较炸弹,再比较牛数,然后比较铁板,最后比较最大卡牌。
接下来我们可以按顺序来写。
我这里把每个回合的玩家用 _player 计为 p1、p2、p3。
发牌
很明显,输入名字,二分找到 id,用字符串一个个输入卡牌,记录五张卡牌和最大卡牌。
出牌
我选择用五层循环枚举出牌方案,先尝试将前四张拼成炸弹,再尝试拼成牛,最后是无牛。用上文写的重载出来的运算符来比较不同牌组之间的大小这时就很方便了。
比较和计分
两两对比大小,再在底分
其实代码也不算很难,作者 60 分钟就打完了。由于我的写法时间复杂度为
#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;
}
:::