0
点赞
收藏
分享

微信扫一扫

poj2315足球游戏

黄昏孤酒 2022-02-13 阅读 16
c++

问题描述:

爱丽丝和鲍勃都非常热爱足球,两人都是先锋。他们都擅长足球控制。一场足球比赛后的一天,他们进行了一场有趣的比赛,他们将足球直接射向球门。球门前有N个足球,他们轮流进行这场比赛。例如,如果轮到爱丽丝,爱丽丝可以选择一些足球(足球的数量必须等于或小于 M)并将它们射向前方。由于足球的质量不是很好,足球不是一个完整的球体,只能滚动其周长的整数倍。而且由于他们的摩擦力和力量的限制,他们无法将足球射出超过L厘米的距离。当然,他们知道足球的半径是 R 厘米。爱丽丝和鲍勃非常喜欢这个游戏。如果他们俩都拥有无限的智商和精准的射门技巧,你能猜出谁能赢得这场足球比赛吗?顺便说一句,虽然爱丽丝和鲍勃一样强壮,但爱丽丝是个女孩,所以她会先出手。

分析:题目大意是两名球员轮流从N个球中挑出不多于M个射门,每个球半径都是R,离球门S。每次只能踢出L以内的距离。进最后一个球者胜,求谁有必胜策略?我们发现对数据进行处理之后,题目等价于给出n堆石子,每堆石子中每次最多取k个石子,每次最多选取m个石子堆做操作的博弈问题,首先我们将每堆石子堆对k+1取模简化运算,取一堆石子上的石子的做法我们是对所有的石子堆的sg值进行xor运算得到sg值,xor又称为半加运算,只进行加法而不进位,对于选取m堆石子的博弈我们的xor则是对于m+1进制下的半加运算,所以我们按位计算这个sg值,模拟m+1进制下的半加运算即可得到答案。

输入:

输入由几个案例组成,每个案例包含两行。
对于每个测试用例,第一行包含 4 个整数 N、M、L 和 R(1 <= M <= N <= 30, 0 < L < 100000000, 0 < R < 10000),用一个空格分隔。N是足球的数量,M是一名球员一回合可以射出的最大足球数,L是一名球员可以射出的最大距离,R是足球的半径。
下一行包含 N 个数字,S(1), S(2), ..., S(N) (0 < S(i) < 100000000),它们描述了足球和球门之间的距离。

输出:

对于每种情况,输出都包含一行描述获胜者的姓名。

样本输入:

 

样本输出:

 程序代码:

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N=30;
const double PI=acos(-1.0);
int n,m,l,r,a[N],sg[N];
int dis(int s)                        //看能否进球
{
     return (int)(s/(2*PI*r))+1;
}
bool solve(){                        //博弈函数
    memset(sg,0,sizeof(sg));
    int k=dis(l);
    for(int i=0;i<n;i++)
      for(int j=0,g=dis(a[i])%k;sg[j]+=g&1,g;j++,g>>=1);
        for(int i=0;i<30;i++)
           if(sg[i]%(m+1))
               return 1;
    return 0;
}
int main(){
    while(~scanf("%d%d%d%d",&n,&m,&l,&r)){
        for(int i=0;i<n;i++)
             scanf("%d",&a[i]);
             puts(solve()?"Alice":"Bob");
    }
    return 0;
}

yjg

举报

相关推荐

0 条评论