题目描述
从瑞神家打牌回来后,东东痛定思痛,决定苦练牌技,终成赌神!
东东有 A × B 张扑克牌。每张扑克牌有一个大小(整数,记为a,范围区间是 0 到 A - 1)和一个花色(整数,记为b,范围区间是 0 到 B - 1。
扑克牌是互异的,也就是独一无二的,也就是说没有两张牌大小和花色都相同。
“一手牌”的意思是你手里有5张不同的牌,这 5 张牌没有谁在前谁在后的顺序之分,它们可以形成一个牌型。 我们定义了 9 种牌型,如下是 9 种牌型的规则,我们用“低序号优先”来匹配牌型,即这“一手牌”从上到下满足的第一个牌型规则就是它的“牌型编号”(一个整数,属于1到9):
- 同花顺: 同时满足规则 2 和规则 3.
- 顺子 : 5张牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
- 同花 : 5张牌都是相同花色的.
- 炸弹 : 5张牌其中有4张牌的大小相等.
- 三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
- 两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
- 三条: 5张牌其中有3张牌的大小相等.
- 一对: 5张牌其中有2张牌的大小相等.
- 要不起: 这手牌不满足上述的牌型中任意一个.
现在, 东东从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种情况的计数。
一些思考
- 记得sort在循环里,sort后重新赋值!!!
记得sort在循环里,sort后重新赋值!!!
记得sort在循环里,sort后重新赋值!!!
本题就是sort后没有重新赋值导致起初WA - 正常情况每次满足条件就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;
- 我往往喜欢调试,很少用输出中间变量判断的方法,今天输出中间变量体验还不错,以后大模拟可以多考虑这种方法。
代码
#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;
}