问题:
从瑞神家打牌回来后,东东痛定思痛,决定苦练牌技,终成赌神!
东东有 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
5 2
1 0 3 1
Output
0 0 0 0 8 0 12 36 0
Input
25 4
0 0 24 3
Output
0 2 18 0 0 644 1656 36432 113344
题解:
这一题,我们就是暴力对五张牌进行比较。统计大小相同的牌的个数以及花色相同的牌的个数,分别放入统计数组中,之后在统计相同个数有多少个(就是两张一样的有多少对,三张一样的有多少)。之后对需要满足的条件进行比较,不过满足就将choice数组相应的位置变一,之后输出最小置一的位置就是其牌型。
这个题其实就是考察我们码力的一个问题,看看你是否能够找到这些牌型所对应的判断条件。
完整代码:
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct card{
int A; //大小
int B; //花色
};
int check(int a1,int b1,int a2,int b2,int a3,int b3,int a4,int b4,int a5,int b5)
{
int choice[10]={0,0,0,0,0,0,0,0,0,0};
int thea[5]={a1,a2,a3,a4,a5};
sort(thea,thea+5);
int counta[5]={0,0,0,0,0};
int theb[5]={b1,b2,b3,b4,b5};
int countb[5]={0,0,0,0,0};
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
if(thea[i]==thea[j])
{
counta[i]++;
}
if(theb[i]==theb[j])
{
countb[i]++;
}
}
}
int one=0,two=0,three=0,four=0,five=0;
for(int i=0;i<5;i++)
{
if(counta[i]==1) one++;
if(counta[i]==2) two++;
if(counta[i]==3) three++;
if(counta[i]==4) four++;
if(counta[i]==5) five++;
}
two=two/2;
three=three/3;
four=four/4;
five=five/5;
if(four==1) //炸弹
{
choice[2]=1;
}
if(three==1&&two==1)
{
choice[3]=1; //三代二
}
if(countb[1]==5)
{
choice[4]=1;
}
if((thea[1]-thea[0]==1)&&thea[2]-thea[1]==1&&thea[3]-thea[2]==1&&thea[4]-thea[3]==1)
{
choice[5]=1;
}
if(choice[4]==1&&choice[5]==1)
{
choice[1]=1;
}
if(three==1&&one==2)
{
choice[6]=1;
}
if(two==2)
{
choice[7]=1;
}
if(two==1&&one==3)
{
choice[8]=1;
}
for(int i=1;i<=8;i++)
{
if(choice[i]==1)
{
return i;
}
}
return 9;
}
int main(int argc, char** argv) {
int a,b;
cin>>a>>b;
int n=a*b;
card pai[n];
int a1,b1,a2,b2;
cin>>a1>>b1>>a2>>b2;
for(int i=0;i<a;i++)
{
for(int j=0;j<b;j++)
{
if(!((i==a1&&j==b1)||(i==a2&&j==b2)))
{
pai[i*b+j].A=i;
pai[i*b+j].B=j;
}
else
{
pai[i*b+j].A=-1;
pai[i*b+j].B=-1; }
}
}
int ans[10]={0,0,0,0,0,0,0,0,0,0};
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
{
if(i==j||j==k||i==k) //不能摸相同的牌;
{
continue;
}
if(pai[i].A==-1||pai[j].A==-1||pai[k].A==-1)
{
continue;
}
int thechoice=check(a1,b1,a2,b2,pai[i].A,pai[i].B,pai[j].A,pai[j].B,pai[k].A,pai[k].B);
ans[thechoice]++;
}
}
}
for(int i=1;i<=9;i++)
{
cout<<ans[i]/6;
if(i!=9)
{
cout<<" ";
}
}
return 0;
}
反思:
这个题的思路其实我也不是一开始就想到的,而是在写的过程中发现本来的方法不对,突然想到之前的化学方程式的问题,发现两个题类似,就找到了这个解法