A-掌握魔法の东东Ⅱ
题目描述
从瑞神家打牌回来后,东东痛定思痛,决定苦练牌技,终成赌神!
东东有 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
解题思路
解答这道题我们必须要遍历所有“一手牌”的可能性,在此基础上再去以低序号优先判断每手牌的“牌型”,判断牌型不难写,用一串“if…else…”即可解决,现在我们要考虑用什么方式去遍历所有的“一手牌”。结合最近所学的内容,我们很容易想到用dfs去枚举所有可能的牌型。
已知有两张牌,我们还需要枚举三张其他的牌,而一张牌有两个性质——大小、花色,因此我们要确定对不同性质的枚举次序。这里我先枚举大小,在大小相同的基础上枚举不同的花色。从第一张牌(0,0)开始枚举,那么第二张牌就枚举到(0,1),那么先将这两张牌确定,再依次向后枚举第三张牌(0,2)、(0,3)…(0,B-1)、(1,0)…直到(A-1,B-1),至此在前两张牌确定了基础上,第三张牌的所有情况枚举完毕,我们开始回溯对第二张牌的枚举(0,2),现在又重复对第三张牌的枚举。当第二张牌枚举到(A-1,B-1),我们就开始回溯对第一张牌枚举(0,1),按此规律依次枚举下去即可。
注意
1、枚举过程中枚举到(a1,b1)、(a2,b2)直接回溯;
2、枚举当一张牌的花色为B-1时,下一张牌直接从(a+1,0)开始枚举,否则就枚举(a,b+1)。
if(b<B-1) {
for(int j=b+1;j<B;++j)
dfs(a,j,n+1);
}
for(int i=a+1;i<A;++i) {
for(int j=0;j<B;++j){
dfs(i,j,n+1);
}
3、一定要注意将存牌数组和判断数组区分开,因为每次判断前都要将这一手牌排序,排序之后已有的牌序被打乱,已枚举的前两张牌在存牌数组中的位置发生改变,而我们对第三张的枚举是建立在前两张牌已确定的基础上的,所以sort前应该将已枚举好的牌复制到新的判断数组中,对新的判断数组的进行排序不会影响已枚举好的前两张牌!
P poker[5];//判断数组
P pp[5];//存牌数组
for(int i=0;i<5;++i) {
poker[i].num=pp[i].num;
poker[i].col=pp[i].col;
}
sort(poker,poker+5);
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct P{
int num,col;
bool operator<(const P &p) const {
return num<p.num;
}
};
P poker[5];//判断数组
P pp[5];//存牌数组
int A,B;
int a1,b1,a2,b2;
int ccc[10]={0};//存储每种牌型编号的方案数
void dfs(int a,int b,int n) {
if((a==a1&&b==b1)||(a==a2&&b==b2)) return;//直接回溯
pp[n+1].num=a,pp[n+1].col=b;
if(n==3) {
for(int i=0;i<5;++i) {
poker[i].num=pp[i].num;
poker[i].col=pp[i].col;
}
sort(poker,poker+5);
if((poker[0].col==poker[1].col)&&(poker[1].col==poker[2].col)&&(poker[2].col==poker[3].col)&&(poker[3].col==poker[4].col)) {
if((poker[0].num+1==poker[1].num)&&(poker[1].num+1==poker[2].num)&&(poker[2].num+1==poker[3].num)&&(poker[3].num+1==poker[4].num))
ccc[1]++;
else ccc[3]++;
}else if(poker[0].num+1==poker[1].num&&poker[1].num+1==poker[2].num&&poker[2].num+1==poker[3].num&&poker[3].num+1==poker[4].num) {
ccc[2]++;
}else if((poker[0].num==poker[1].num&&poker[1].num==poker[2].num&&poker[2].num==poker[3].num)||
(poker[1].num==poker[2].num&&poker[2].num==poker[3].num&&poker[3].num==poker[4].num)) {
ccc[4]++;
}else if((poker[0].num==poker[1].num&&poker[1].num==poker[2].num&&poker[3].num==poker[4].num)||
(poker[0].num==poker[1].num&&poker[2].num==poker[3].num&&poker[3].num==poker[4].num)) {
ccc[5]++;
}else if((poker[0].num==poker[1].num&&poker[2].num==poker[3].num)||(poker[0].num==poker[1].num&&poker[3].num==poker[4].num)
||(poker[1].num==poker[2].num&&poker[3].num==poker[4].num)) {
ccc[6]++;
}else if((poker[0].num==poker[1].num&&poker[1].num==poker[2].num)||(poker[2].num==poker[3].num&&poker[3].num==poker[4].num)
||(poker[1].num==poker[2].num&&poker[2].num==poker[3].num)) {
ccc[7]++;
}else if(poker[0].num==poker[1].num||poker[1].num==poker[2].num||poker[2].num==poker[3].num||poker[3].num==poker[4].num) {
ccc[8]++;
}else ccc[9]++;
return ;
}
if(b<B-1) {
for(int j=b+1;j<B;++j)
dfs(a,j,n+1);
}
for(int i=a+1;i<A;++i) {
for(int j=0;j<B;++j){
dfs(i,j,n+1);
}
}
}
int main() {
scanf("%d %d",&A,&B);
scanf("%d %d %d %d",&a1,&b1,&a2,&b2);
pp[0].num=a1;pp[0].col=b1;pp[1].num=a2;pp[1].col=b2;
for(int i=0;i<A;++i) {
for(int j=0;j<B;++j)
dfs(i,j,1);
}
for(int i=1;i<=9;++i)
printf("%d ",ccc[i]);
printf("\n");
}