SDU_week6_大模拟_A - 掌握魔法の东东 II(打牌模拟)

题目描述

从瑞神家打牌回来后,东东痛定思痛,决定苦练牌技,终成赌神!
东东有 A × B 张扑克牌。每张扑克牌有一个大小(整数,记为a,范围区间是 0 到 A - 1)和一个花色(整数,记为b,范围区间是 0 到 B - 1。
扑克牌是互异的,也就是独一无二的,也就是说没有两张牌大小和花色都相同。
“一手牌”的意思是你手里有5张不同的牌,这 5 张牌没有谁在前谁在后的顺序之分,它们可以形成一个牌型。 我们定义了 9 种牌型,如下是 9 种牌型的规则,我们用“低序号优先”来匹配牌型,即这“一手牌”从上到下满足的第一个牌型规则就是它的“牌型编号”(一个整数,属于1到9):

  1. 同花顺: 同时满足规则 2 和规则 3.
  2. 顺子 : 5张牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
  3. 同花 : 5张牌都是相同花色的.
  4. 炸弹 : 5张牌其中有4张牌的大小相等.
  5. 三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
  6. 两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
  7. 三条: 5张牌其中有3张牌的大小相等.
  8. 一对: 5张牌其中有2张牌的大小相等.
  9. 要不起: 这手牌不满足上述的牌型中任意一个.

现在, 东东从A × B 张扑克牌中拿走了 2 张牌!分别是 (a1, b1) 和 (a2, b2). (其中a表示大小,b表示花色)
现在要从剩下的扑克牌中再随机拿出 3 张!组成一手牌!!
其实东东除了会打代码,他业余还是一个魔法师,现在他要预言他的未来的可能性,即他将拿到的“一手牌”的可能性,我们用一个“牌型编号(一个整数,属于1到9)”来表示这手牌的牌型,那么他的未来有 9 种可能,但每种可能的方案数不一样。
现在,东东的阿戈摩托之眼没了,你需要帮他算一算 9 种牌型中,每种牌型的方案数。

Input
第 1 行包含了整数 A 和 B (5 ≤ A ≤ 25, 1 ≤ B ≤ 4).
第 2 行包含了整数 a1, b1, a2, b2 (0 ≤ a1, a2 ≤ A - 1, 0 ≤ b1, b2 ≤ B - 1, (a1, b1) ≠ (a2, b2)).

Output
输出一行,这行有 9 个整数,每个整数代表了 9 种牌型的方案数(按牌型编号从小到大的顺序)

Examples
Input
5 2
1 0 3 1

Output
0 8 0 0 0 12 0 36 0

Input
25 4
0 0 24 3

Output
0 0 0 2 18 1656 644 36432 113344

题目分析

这是一道大模拟题,要求我们统计(给定数据+遍历数据)的组合属于九种牌型中的哪种牌型
根据以往大模拟题的经验,先定义结构体和比较函数,从而对每次的手牌分类。在main函数中,首先读入点数A和花色数B,然后读入已有的两张手牌。利用排列组合寻找后三张牌,获得五张手牌后对其排序。排列组合记住这个套路:

for (int i = 0; i < sum - 2; ++i)
    for (int j = i + 1; j < sum - 1; ++j)
        for (int k = j + 1; k < sum; ++k)

然后按照优先级降低顺序依次判断9种情况,倘若满足条件,continue本次循环。最后依次输出9种情况的计数。

一些思考

  1. 记得sort在循环里,sort后重新赋值!!!
    记得sort在循环里,sort后重新赋值!!!
    记得sort在循环里,sort后重新赋值!!!
    本题就是sort后没有重新赋值导致起初WA
  2. 正常情况每次满足条件就continue,但是出现了双重循环,在内循环成立,怎么跳出外循环?举例如下:
for (int i = 0; i < A; i++)
{
	if (jishu[i] == 2)
	{
		two++;
		if (two == 2)
		{//6
			paixing[6]++;
			//state[6] = true;
			break;
		}
	}
}

即使正确记录paixing[6]++;代码依然会继续进行,采用的策略上注释处记录已成功,然后在下面判断:

if (state[6] == true)continue;
  1. 我往往喜欢调试,很少用输出中间变量判断的方法,今天输出中间变量体验还不错,以后大模拟可以多考虑这种方法。

代码

#define _CRT_SECURE_NO_WARNINGS
#define _ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#include <bits/stdc++.h>
//#include <iostream>
//#include<algorithm>

using namespace std;

struct poker {
    int num;
    int color;
};

bool cmp(poker a, poker b)
{
    if (a.num != b.num)return a.num < b.num;
    else return a.color < b.color;
}

poker myset[110];//所有牌
int paixing[10];//1-9为牌型数

int main()
{
    memset(paixing, 0, sizeof(paixing));
    int A, B;
    cin >> A >> B;
    int sum = A * B;//总牌数

    int temp = 0;
    for (int i = 0; i < A; i++)
    {//存牌
        for (int j = 0; j < B; j++)
        {
            myset[temp].num = i;
            myset[temp].color = j;
            temp++;
            //cout << myset[temp - 1].num << myset[temp - 1].color << endl;
        }
    }

    poker mypoker[6];//手牌
    int a1, a2, b1, b2;
    cin >> a1 >> b1 >> a2 >> b2;

    for (int i = 0; i < sum - 2; ++i)
        for (int j = i + 1; j < sum - 1; ++j)
            for (int k = j + 1; k < sum; ++k)
            {//组合数,获得手牌
                mypoker[1].num = a1;//记得sort在循环里,sort后重新赋值!!!
                mypoker[1].color = b1;//记得sort在循环里,sort后重新赋值!!!
                mypoker[2].num = a2;//记得sort在循环里,sort后重新赋值!!!
                mypoker[2].color = b2;//记得sort在循环里,sort后重新赋值!!!
                if (myset[i].num == mypoker[1].num && myset[i].color == mypoker[1].color)continue;
                if (myset[i].num == mypoker[2].num && myset[i].color == mypoker[2].color)continue;
                if (myset[j].num == mypoker[1].num && myset[j].color == mypoker[1].color)continue;
                if (myset[j].num == mypoker[2].num && myset[j].color == mypoker[2].color)continue;
                if (myset[k].num == mypoker[1].num && myset[k].color == mypoker[1].color)continue;
                if (myset[k].num == mypoker[2].num && myset[k].color == mypoker[2].color)continue;
                mypoker[3].num = myset[i].num;
                mypoker[3].color = myset[i].color;
                mypoker[4].num = myset[j].num;
                mypoker[4].color = myset[j].color;
                mypoker[5].num = myset[k].num;
                mypoker[5].color = myset[k].color;
                //for (int i = 1; i <= 5; i++)cout << mypoker[i].num << " " << mypoker[i].color << endl;
                //cout << endl;

                sort(mypoker + 1, mypoker + 6, cmp);
                bool state[10];
                memset(state, 0, sizeof(state));
                
                if (mypoker[1].color == mypoker[2].color && mypoker[1].color == mypoker[3].color && mypoker[1].color == mypoker[4].color && mypoker[1].color == mypoker[5].color)
                {//1
                    if (mypoker[1].num == mypoker[2].num - 1 && mypoker[2].num == mypoker[3].num - 1 && mypoker[3].num == mypoker[4].num - 1 && mypoker[4].num == mypoker[5].num - 1)
                    {
                        paixing[1]++;
                        continue;
                    }
                }
                if (mypoker[1].num == (mypoker[2].num - 1) && mypoker[2].num == (mypoker[3].num - 1) && mypoker[3].num == (mypoker[4].num - 1) && mypoker[4].num == (mypoker[5].num - 1))
                {//2
                    paixing[2]++;
                    continue;
                }
                if (mypoker[1].color == mypoker[2].color && mypoker[1].color == mypoker[3].color && mypoker[1].color == mypoker[4].color && mypoker[1].color == mypoker[5].color)
                {//3
                    paixing[3]++;
                    continue;
                }

                int jishu[30];//统计每种牌数的箱子
                memset(jishu, 0, sizeof(jishu));
                bool four = false;
                bool three = false;
                //bool two = false;
                for (int i = 1; i <= 5; i++)
                {
                    jishu[mypoker[i].num]++;
                    if (jishu[mypoker[i].num] == 4)
                        four = true;
                    if (jishu[mypoker[i].num] == 3)
                        three = true;
                }

                if (four == true)
                {//4
                    paixing[4]++;
                    continue;
                }
                else if (three == true)
                {
                    for(int i=0;i<A;i++)
                        if (jishu[i] == 2)
                        {//5
                            paixing[5]++;
                            state[5] = true;
                            break;
                        }
                }
                if (state[5] == true)continue;

                int two = 0;
                for (int i = 0; i < A; i++)
                {
                    if (jishu[i] == 2)
                    {
                        two++;
                        if (two == 2)
                        {//6
                            paixing[6]++;
                            state[6] = true;
                            break;
                        }
                    }
                }
                if (state[6] == true)continue;

                if (four != true && three == true)
                {//7
                    paixing[7]++;
                    continue;
                }

                if (two == 1)
                {//8
                    paixing[8]++;
                    continue;
                }

                paixing[9]++;
            }

    for (int i = 1; i <= 9; i++)
    {
        if (i == 1)cout << paixing[1];
        else cout << " " << paixing[i];
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值