A - 掌握魔法の东东 II
题目描述
从瑞神家打牌回来后,东东痛定思痛,决定苦练牌技,终成赌神!
东东有 A × B 张扑克牌。每张扑克牌有一个大小(整数,记为a,范围区间是 0 到 A - 1)和一个花色(整数,记为b,范围区间是 0 到 B - 1。
扑克牌是互异的,也就是独一无二的,也就是说没有两张牌大小和花色都相同。
“一手牌”的意思是你手里有5张不同的牌,这 5 张牌没有谁在前谁在后的顺序之分,它们可以形成一个牌型。 我们定义了 9 种牌型,如下是 9 种牌型的规则,我们用“低序号优先”来匹配牌型,即这“一手牌”从上到下满足的第一个牌型规则就是它的“牌型编号”(一个整数,属于1到9):
1.同花顺: 同时满足规则 5 和规则 4.
2.炸弹 : 5张牌其中有4张牌的大小相等.
3.三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
4.同花 : 5张牌都是相同花色的.
5.顺子 : 5张牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
6.三条: 5张牌其中有3张牌的大小相等.
7.两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
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 种牌型的方案数(按牌型编号从小到大的顺序)
Sample Input 1
5 2
1 0 3 1
Sample Output 1
0 0 0 0 8 0 12 36 0
Sample Input 2
25 4
0 0 24 3
Sample Output 2
0 2 18 0 0 644 1656 36432 113344
题解
结构体card代表一张卡牌,a是一共有多少数字,b是一共有多少花色,card_form数组是存放九种牌型现有的个数(运行过程中从0开始加),card型数组v存放的是除了东东抽到的牌之外生下了什么牌(数量有a* b-2个),card型数组cc存放的是运行过程中已经选择的卡牌(没选择完之前不满五个),card型数组c是选出五张卡牌之后复制cc的内容,便于在c中排序并检查它是哪一种牌型。
递归函数count_card产生分支,对每个牌都有选与不选两种选择,产生两个分支。count_card的参数为n和k,n表示这一步是对v[n]的选择(0<=n<a*b-2),k是该选择第几个卡牌了(3>=k<=1)。在每个函数中对第v[n]个卡牌有选择它和不选它两种情况,选择它就cc[k]=v[n],进入下一层函数count_card(n-1,k-1),不选它就直接count_card(n-1,k)。
在每进入一次count_card()函数,就检查一次k和n的值,k=0则证明东东手中的牌选满了,检查牌型,n=0证明所有的牌已经选完了,但东东的牌不够五张,不符合要求,直接返回即可。
检查五张牌的牌型时,可以直接从牌型1到牌型9依次检查,符合则card_form[i]++。也可以根据他们的构成关系(如满足1就一定满足4和5),使用多重条件语句检查牌型。
判断多个数的相等时,不能用a= =b= =c而应该用a= =b&&b= =c。
代码
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
struct card{
int a,b;//一共有数字 花色
bool operator<(const card&c)const{
return a<c.a;
}
};
int a,b;//数字 花色
int card_form[10];//1~9:9种牌型
vector<card>v;
card cc[6];//1~5
vector<card>c;
bool yidui(){
if(c[0].a==c[1].a){
return 1;
}else if(c[2].a==c[1].a){
return 1;
}else if(c[3].a==c[2].a){
return 1;
}else if(c[4].a==c[3].a){
return 1;
}else{return 0;}
}
bool liangdui(){
if(c[1].a==c[0].a&&c[3].a==c[2].a){
return 1;
}else if(c[2].a==c[1].a&&c[4].a==c[3].a){
return 1;
}else if(c[3].a==c[4].a&&c[1].a==c[0].a){
return 1;
}else{return 0;}
}
bool santiao(){
if((c[1].a==c[0].a&&c[2].a==c[1].a)||(c[1].a==c[2].a&&c[2].a==c[3].a)||(c[2].a==c[4].a&&c[4].a==c[3].a)){
return 1;
}else{return 0;}
}
bool shunzi(){
int tmp=c[0].a;
for(int i=1;i<5;i++){
if(c[i].a==tmp+1){
tmp=c[i].a;
}else{return 0;}
}
return 1;
}
bool tonghua(){
int tmp=c[0].b;
for(int i=1;i<5;i++){
if(c[i].b!=tmp){return 0;}
}
return 1;
}
bool sandaier(){
if((c[1].a==c[0].a&&c[3].a==c[4].a&&c[4].a==c[2].a)||(c[4].a==c[3].a&&c[0].a==c[2].a&&c[1].a==c[2].a)){
return 1;
}else{return 0;}
}
bool zhadan(){
if(c[1].a==c[2].a&&c[2].a==c[3].a&&c[2].a==c[0].a||c[1].a==c[2].a&&c[2].a==c[3].a&&c[2].a==c[4].a){
return 1;
}else{return 0;}
}
void count_card(int n,int k){//k是还能选几张牌,n是还剩几张牌
if(k==0){
while(!c.empty()){c.pop_back();}
for(int i=1;i<=5;i++){
c.push_back(cc[i]);
}
sort(c.begin(),c.end());
if(yidui()){
if(liangdui()){
if(zhadan()){
card_form[2]++;
}else if(sandaier()){
card_form[3]++;
}else{
card_form[7]++;
}
}else if(santiao()){
card_form[6]++;
}
else{
card_form[8]++;
}
}
else if(tonghua()){
if(shunzi()){
card_form[1]++;
}else{
card_form[4]++;
}
}
else if(shunzi()){
card_form[5]++;
}else{
card_form[9]++;
}
return;
}
if(n<=-1){return;}
cc[k].a=v[n].a; cc[k].b=v[n].b;
count_card(n-1,k-1);
count_card(n-1,k);
}
int main(int argc, char** argv) {
scanf("%d%d",&a,&b);
scanf("%d%d%d%d",&cc[4].a,&cc[4].b,&cc[5].a,&cc[5].b);
for(int i=0;i<a;i++){
for(int j=0;j<b;j++){
if((cc[4].a==i&&cc[4].b==j)||(cc[5].a==i&&cc[5].b==j)){
continue;
}
card tmp={i,j};
v.push_back(tmp);
}
}
count_card(a*b-3,3);
for(int i=1;i<=9;i++){
printf("%d ",card_form[i]);
}
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)