两个人打台球,初始状态为n个编号不同的球和一个母球(编号为0),每个球的分数即它的编号,每次操作时,当前的目标球为台面上球的最小值,操作犯规的话会给对手加上若干分,犯规的情况有:
1 母球没有打到任何球,对手+目标球的分数
2 母球没有落袋,但是母球第一次撞击没有撞到目标球,或者是第一次撞击同时撞击了1个以上的球,对手+第一次同时撞击到的球中编号最大的分数
3 母球落袋并且撞击到了至少一个球,对手+第一次同时撞击到的球中编号最大的分数
在没有犯规的情况下,若目标球落袋,则我方的分数加上本轮落袋的球的分数和,并且下一轮依然是我方操作。如果我方犯规,或者是有球落袋但是目标球没有落袋,则对方再加上落袋的球的分数和。所有操作结束后,求A:B的分数。
很考验细心的一道模拟,注意到,我方得分的情况只有首先只撞到了一个球,并且这个球是目标球,并且母球没有落袋,目标球落袋,这种情况下我方加分,并继续行动,否则一定是对方加分并且换手,其中对方加分的情况中有一点要考虑到,如果我方犯规了,对方会加上罚分,并且如果这次操作有球落袋了,对手会再加上落袋求的分数和。考虑到这些,写的时候细心点这题也就没什么大问题了...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int pt[3];
int a[1010];
int b[1010];
int c[1010];
bool f[101000];
int n,m,k,x,y,z,p,q;
int x1,x2,x3,y1,y2,y3;
int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
memset(f,false,sizeof f);
memset(pt,0,sizeof pt);
int tgt=20200;
for (int i=1; i<=n; i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
tgt=a[1];
int tgtnum=1;
int side=0;
int ad=side;
int sum;
for (int i=1; i<=m; i++)
{
f[0]=false;
scanf("%d",&p);
int minn=0;
int minb=0;
for (int i=1; i<=p; i++) scanf("%d",&b[i]),minn=max(minn,b[i]);
if (p==1 && b[1]==tgt)
{
scanf("%d",&q);
sum=0;
minb=0;
for (int i=1; i<=q; i++)
{
scanf("%d",&c[i]),minb=max(minb,c[i]),sum+=c[i];
f[c[i]]=true;
}
if (f[0])
{
pt[side^1]+=minn;
pt[side^1]+=sum;
side^=1;
}
else
{
if (f[tgt]) pt[side]+=sum;
else pt[side^1]+=sum,side^=1;
}
}
else
{
scanf("%d",&q);
minb=0;
sum=0;
for (int i=1; i<=q; i++)
scanf("%d",&c[i]),minb=max(minb,c[i]),sum+=c[i],f[c[i]]=true;
if (p==0) pt[side^1]+=tgt;
else if (!f[0]) pt[side^1]+=minn;
if (f[0] && p>0) pt[side^1]+=minn;
pt[side^1]+=sum;
side^=1;
}
while(f[a[tgtnum]] && tgtnum<=n) tgtnum++;
if (tgtnum>n) break;
tgt=a[tgtnum];
}
cout<<pt[0]<<" : "<<pt[1]<<endl;
}
return 0;
}
本文介绍了一款台球游戏的模拟算法实现细节。重点讨论了游戏中的得分规则及各种可能的操作情况,包括正常得分、犯规及换手等情况。通过细致的流程控制实现了游戏过程的精确模拟。

被折叠的 条评论
为什么被折叠?



