ZOJ3757:Alice and Bob and Cue Sports(模拟)

Alice and Bob both love playing games. Now, Alice and Bob are playing a cue sport like Nine-ball Pool. Two players move in turn. A move is that one player use the cue ball to hit the target ball for pocketing the target ball. At the beginning of game, there are one cue ball and n object balls. Each object ball has a number (a positive integer) on it, and no two object balls have the same number. In a move, the target ball is a object ball still on the table with the smallest number. If the player does the following things in a move, a foul is called and a penalty point is added to the opposite's point:

  • Cue ball do not hit any object ball. Penalty: the number of target ball.
  • Cue ball is not pocketed and hit at least one ball, but do not hit target ball first or hit more than one object ball first at the same time. Penalty: the largest number of ball in the first hit balls.
  • Cue ball is pocketed and hit at least one ball. Penalty: the largest number of ball in the first hit balls.
If the player pockets the target ball without a foul, a point will be added to the player's points, which is the sum of numbers of the ball pocketed in this move, and the player can make another move. But, if the player pockets the target ball with a foul or pockets at least one object ball not including the target ball, this point will be added to the opposite's points. If cue ball is pocketed, it will be pull out of the pocket and put on the table again while object balls will not be put on the table again after they are pocketed, even if the player pocketed them with a foul.

Now given n object balls and m moves, Bob wants to write a program to calculate the final points of Alice and him after these m moves. Because of Lady's first Rule, Alice always moves first.

Input

There are multiple cases. The first line of each case consists of two integers, n and m (1 ≤ n ≤ 1000, 0 ≤ m ≤ 1000), as described above. The second line consists of n positive integers. Each integer ai means the number of ith object ball (1 ≤ ai ≤ 10000). There are 2m lines followed. The (2i-1)th and (2i)th lines describe the ith move. The (2i-1)th line first includes an integer p, meaning cue ball hits p balls first. There are p integers followed in the same line, describing the hit balls. The (2i)th line first includes an integer q, meaning there are q balls pocketed. There are q integers followed in the same line, describing the pocketed balls (0 means cue ball). It's guaranteed that there is no impossible data.

Output

For each case, output one line as the format: "AP : BP", where AP means Alice's points and BP means Bob's points.

Sample Input
3 3
2 3 5
1 2
1 2
1 3
1 5
1 3
1 3
Sample Output
2 : 8
 
对于一个英语四级还没过的渣渣来说,这道题我看了好久都没看懂。。。。
下面贴出别人的题意。。。
 
两个人打台球,初始状态为n个编号不同的球和一个母球(编号为0),每个球的分数即它的编号,每次操作时,当前的目标球为台面上球的最小值,操作犯规的话会给对手加上若干分,犯规的情况有:

1  母球没有打到任何球,对手+目标球的分数

2 母球没有落袋,但是母球第一次撞击没有撞到目标球,或者是第一次撞击同时撞击了1个以上的球,对手+第一次同时撞击到的球中编号最大的分数

3 母球落袋并且撞击到了至少一个球,对手+第一次同时撞击到的球中编号最大的分数

在没有犯规的情况下,若目标球落袋,则我方的分数加上本轮落袋的球的分数和,并且下一轮依然是我方操作。如果我方犯规,或者是有球落袋但是目标球没有落袋,则对方再加上落袋的球的分数和。所有操作结束后,求A:B的分数。

很考验细心的一道模拟,注意到,我方得分的情况只有首先只撞到了一个球,并且这个球是目标球,并且母球没有落袋,目标球落袋,这种情况下我方加分,并继续行动,否则一定是对方加分并且换手,其中对方加分的情况中有一点要考虑到,如果我方犯规了,对方会加上罚分,并且如果这次操作有球落袋了,对手会再加上落袋求的分数和。考虑到这些,写的时候细心点这题也就没什么大问题了...

翻译出处:http://blog.csdn.net/night_raven/article/details/20320575

翻译这么详细,真是一位大神了。。。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int s[10000],hash[200000];
int hit[10000],in[10000];
int a[2],i,j,pot,l_hit,l_in,n,m,flag,flag_pot;

void set()
{
    for(int k=0; k<l_in; k++)
        hash[in[k]]=1;
    while(hash[s[pot]])
        pot++;
    flag=1-flag;
}

void solve()
{
    int sum=0;
    for(int k=0; k<l_in; k++)
        sum+=in[k];
    if(l_hit==0) //没击中球
    {
        a[1-flag]+=s[pot];
    }
    else if(in[0]==0&&l_in!=0) //先判断是否有球入袋
    {
        a[1-flag]+=hit[l_hit-1];
    }
    else if(l_hit>1||(l_hit==1&&hit[0]!=s[pot])) //过多或不是目标球
    {
        a[1-flag]+=hit[l_hit-1];
    }
    else //无犯规
    {
        if(flag_pot) //目标球进了
        {
            a[flag]+=sum;
            flag=1-flag;
            return;
        }
    }
    if(in==0) return;
    a[1-flag]+=sum;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        a[1] = a[0] = 0;
        for(i = 1; i<=n; i++)
            scanf("%d",&s[i]);
        sort(s+1,s+n+1);
        memset(hash,0,sizeof(hash));
        flag = 0;
        pot = 1;
        for(i = 0; i<m; i++)
        {
            flag_pot = 0;
            scanf("%d",&l_hit);
            for(j = 0; j<l_hit; j++)
                scanf("%d",&hit[j]);
            scanf("%d",&l_in);
            for(j = 0; j<l_in; j++)
            {
                scanf("%d",&in[j]);
                if(in[j] == s[pot])
                flag_pot = 1;
            }
            sort(hit,hit+l_hit);
            sort(in,in+l_in);
            solve();
            set();
        }
        printf("%d : %d\n",a[0],a[1]);
    }

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值