玩骰子

玩骰子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
  Nias与Ains都特别喜欢玩骰子,而且都自以为比对方玩得更溜。
  终于有一天,他们决定用骰子来一决高下!
  一般的骰子玩法已经不足以体现他们的水平了,于是他们自创了一套玩法来PK:
首先,每人掷3个骰子;之后,可以选择其中一个骰子重新掷(当然也可以放弃这一步),最后,比较投掷结果的大小,结果大的那方获胜,一样的话为平局。
  大小比较规则为:
  三个一样数字的骰子称为三条;两个一样数字的骰子称为对子;只有一个数字的骰子成为散牌。三条>对子>散牌。当双方结果都为三条时,直接比较三条数字的大小;都有对子时,先比较对子数字的大小,若相同,再比较剩下的骰子的数字的大小;都只有散牌时,先比较最大的数字的大小,若相同,再比较次大的数字的大小,还相同,最后比较最小的数字的大小。

  现在Nias已经投了3个骰子,还剩一次机会可以选择其中一个骰子重新投(或不选),而且他已经知道了Ains的最后投掷结果,求Nias获胜的概率有多大。
 

Input
输入数据第一行为一个整数T,表示有T组测试数据。
接下来T行,每行6个1~6的整数,前三个表示Nias第一次的投掷结果,后三个表示Aias最终的投掷结果。
 

Output
请输出Nias获胜的概率,结果保留3位小数,每组输出占一行。
 

Sample Input
  
  
4 2 3 5 3 3 4 3 3 1 2 2 2 6 2 1 5 4 3 1 2 3 4 4 1
 

Sample Output
  
  
0.333 0.167 1.000 0.000

解题思路:先排序进行分类俩个人的骰子属于什么牌,然后判断是否能赢,如果能直接输出,否则:3个骰子逐个进行6点枚举,每次枚举排序进行分类,然后俩个人比较大小,累计胜率,3个骰子全部枚举完寻找最大胜率即可。

参考:点击打开链接

#include<stdio.h>
#include<stdlib.h>
int a[3],b[3],temp[3],flag_a,flag_b;
int cmp(const void *a,const void *b)
{
    return *(int*)b - *(int *)a;
}

int classily(int x[])//分类:三条,对子,散牌
{
    if(x[0] == x[2])//已排序,所以只需判断第一个和最后一个就知道是否为三条
        return 3;
    if(x[0] == x[1] || x[1] == x[2])
        return 2;
    else
        return 1;

}
int judge()//比较俩人在各种情况下的输赢
{
    if(flag_a > flag_b)//大于直接赢
        return 1;
    if(flag_a == flag_b)
    {
        if(flag_a == 3)//同时为三条时
        {
            if(temp[0] > b[0])
                return 1;
            else
                return 0;
        }
        if(flag_a == 2)//同时为对子时
        {
            if(temp[1] > b[1])//已排序,所以出现中间的那个数必为对子数
                return 1;
            if(temp[1] == b[1])//如果对子数相等,比较剩余的那个数大小
            {
                int temp_a = temp[0] == temp[1]?temp[2]:temp[0];//中间数与第一个数比较,相等即第三个数即为剩余数,否则第一个即为
                int temp_b = b[0] == b[1]? b[2]: b[0];
                if(temp_a > temp_b)
                    return 1;
                else
                    return 0;
            }
            else
                return 0;

        }
        if(flag_a == 1)//同时为散牌时,逐个判断
        {
            if(temp[0] > b[0])
                return 1;
            else if(temp[0] == b[0])
            {
                if(temp[1] > b[1])
                    return 1;
                else if(temp[1] == b[1])
                {
                    if(temp[2] > b[2])
                        return 1;
                    else
                        return 0;
                }
                else
                    return 0;
            }
            else
                return 0;

        }
    }
return 0;//小于即为0}
int main()
{
    int t,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d%d%d",&a[0],&a[1],&a[2],&b[0],&b[1],&b[2]);
        qsort(a,3,sizeof(a[0]),cmp);
        qsort(b,3,sizeof(b[0]),cmp);
        flag_a = classily(a);
        flag_b = classily(b);
        for(i=0;i<3;i++)
            temp[i] = a[i];
        if(judge())//不选直接赢输出
        {
            printf("1.000\n");
            continue;
        }

        int max = -1;
        for(i=0;i<3;i++)//3个骰子逐个枚举
        {
            int sum = 0;
            for(j=1;j<=6;j++)
            {
                temp[0] = j;//进行枚举
                temp[1] = a[(i+1)%3];//调换顺序
                temp[2] = a[(i+2)%3];
                qsort(temp,3,sizeof(temp[0]),cmp);//递减排序
                flag_a = classily(temp);//进行分类
                if(judge())//判断能赢几次
                    sum++;
            }
            if(sum > max)//寻找最大胜率
                max = sum;
        }
        printf("%.3lf\n",max/6.0);

    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值