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 种牌型中,每种牌型的方案数。
输入:
第 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)).
输出:
输出一行,这行有 9 个整数,每个整数代表了 9 种牌型的方案数(按牌型编号从小到大的顺序)
样例:
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

对于前三种牌型,分别写3个函数来判断,其中同花顺通过同花和顺子的函数辅助判断。
对于顺子,因为顺子要求五张牌必须为x,x+1,x+2,x+3,x+4,则调用sort函数先进行排序,然后取最小的牌,设x为该牌的值+1,循环4次,每次x+1,判断牌的值是否与x相同,若不同,说明不是顺子,若相同,则是顺子。

bool rule2(card c1,card c2,card c3)//判断是否是顺子 
{
 temp[0]=c1;temp[1]=c2;temp[2]=c3;temp[3]=card1;temp[4]=card2;
 sort(temp,temp+5,comp);
 int x=temp[0].a+1;
 for(int i=1;i<5;i++)
 {
  if(temp[i].a!=x)
  {
   return false;
  }
  x++;
 }
 return true;
}

对于同花,任取一张牌,设b为该牌的花色,然后循环判断其余四张牌是否花色都是b。

bool rule3(card c1,card c2,card c3)//判断是否是同花 
{
 temp[0]=c1;temp[1]=c2;temp[2]=c3;temp[3]=card1;temp[4]=card2;
 int b=temp[0].b;
 for(int i=1;i<5;i++)
 {
  if(temp[i].b!=b)
  {
   return false;
  }
 }
 return true;
}

同花顺利用上两个函数进行判断。

bool rule1(card c1,card c2,card c3)//根据前两个函数判断是否是同花顺 
{
 if(rule2(c1,c2,c3)&&rule3(c1,c2,c3))
 {
  return true;
 }
 return false;
}

对于其余6中牌型,利用函数rule45678()判断,用五个整型变量,分别记录五个数中与某个数相同的数字个数,然后将那五个整型变量相加,不同的牌型对应着一个特殊的和,可以利用和来判断牌型。

int rule45678(card c1,card c2,card c3)//判断剩余情况 
{
 temp[0]=c1;temp[1]=c2;temp[2]=c3;temp[3]=card1;temp[4]=card2;
 int count1=0,count2=0,count3=0,count4=0,count5=0;
 int num1=temp[0].a,num2=temp[1].a,num3=temp[2].a,num4=temp[3].a,num5=temp[4].a;
 for(int i=0;i<5;i++)//遍历一遍,对于每个数,分别记下五个数中与该数相同的数字个数 
 {
  if(temp[i].a==num1)
  {
   count1++;
  }
  if(temp[i].a==num2)
  {
   count2++;
  }
  if(temp[i].a==num3)
  {
   count3++;
  }
  if(temp[i].a==num4)
  {
   count4++;
  }
  if(temp[i].a==num5)
  {
   count5++;
  }
 }
 int sum=count1+count2+count3+count4+count5;
 int ans=0;
 switch(sum)
 {
  case 17://count1~count5的值为 4 4 4 4 1
   ans=3;
   break;
  case 13://count1~count5的值为 3 3 3 2 2
   ans=4;
   break;
  case 9://count1~count5的值为 2 2 2 2 1
   ans=5;
   break;
  case 11://count1~count5的值为 3 3 3 1 1
   ans=6;
   break;
  case 7://count1~count5的值为 2 2 1 1 1
   ans=7;
   break;
  default://count1~count5的值为 1 1 1 1 1
   ans=8;
   break;
 }
 return ans;
}

以下是完整代码:

#include<iostream>
#include<algorithm>
using namespace std;
struct card{
 int a,b;
};
int A,B;
int type[9];//九种可能牌型的数量 
card c[110];
card card1,card2;
int cnt;
card temp[5];
bool comp(card c1,card c2)
{
 if(c1.a<c2.a)
 return true;
 else
 return false;
}
bool rule2(card c1,card c2,card c3)//判断是否是顺子 
{
 temp[0]=c1;temp[1]=c2;temp[2]=c3;temp[3]=card1;temp[4]=card2;
 sort(temp,temp+5,comp);
 int x=temp[0].a+1;
 for(int i=1;i<5;i++)
 {
  if(temp[i].a!=x)
  {
   return false;
  }
  x++;
 }
 return true;
}
bool rule3(card c1,card c2,card c3)//判断是否是同花 
{
 temp[0]=c1;temp[1]=c2;temp[2]=c3;temp[3]=card1;temp[4]=card2;
 int b=temp[0].b;
 for(int i=1;i<5;i++)
 {
  if(temp[i].b!=b)
  {
   return false;
  }
 }
 return true;
}
bool rule1(card c1,card c2,card c3)//根据前两个函数判断是否是同花顺 
{
 if(rule2(c1,c2,c3)&&rule3(c1,c2,c3))
 {
  return true;
 }
 return false;
}
int rule45678(card c1,card c2,card c3)//判断剩余情况 
{
 temp[0]=c1;temp[1]=c2;temp[2]=c3;temp[3]=card1;temp[4]=card2;
 int count1=0,count2=0,count3=0,count4=0,count5=0;
 int num1=temp[0].a,num2=temp[1].a,num3=temp[2].a,num4=temp[3].a,num5=temp[4].a;
 for(int i=0;i<5;i++)//遍历一遍,对于每个数,分别记下五个数中与该数相同的数字个数 
 {
  if(temp[i].a==num1)
  {
   count1++;
  }
  if(temp[i].a==num2)
  {
   count2++;
  }
  if(temp[i].a==num3)
  {
   count3++;
  }
  if(temp[i].a==num4)
  {
   count4++;
  }
  if(temp[i].a==num5)
  {
   count5++;
  }
 }
 int sum=count1+count2+count3+count4+count5;
 int ans=0;
 switch(sum)
 {
  case 17://count1~count5的值为 4 4 4 4 1
   ans=3;
   break;
  case 13://count1~count5的值为 3 3 3 2 2
   ans=4;
   break;
  case 9://count1~count5的值为 2 2 2 2 1
   ans=5;
   break;
  case 11://count1~count5的值为 3 3 3 1 1
   ans=6;
   break;
  case 7://count1~count5的值为 2 2 1 1 1
   ans=7;
   break;
  default://count1~count5的值为 1 1 1 1 1
   ans=8;
   break;
 }
 return ans;
}
int main()
{
 for(int i=0;i<9;i++)
 {
  type[i]=0;
 }
 cin>>A>>B;
 cin>>card1.a>>card1.b>>card2.a>>card2.b; 
 cnt=0;
 for(int i=0;i<=A-1;i++)
 {
  for(int j=0;j<=B-1;j++)
  {
   if((i==card1.a&&j==card1.b)||(i==card2.a&&j==card2.b))
   continue;
   c[cnt].a=i;c[cnt].b=j;
   cnt++;
  }
 }
 for(int i=0;i<cnt-2;i++)
 {
  for(int j=i+1;j<cnt-1;j++)
  {
   for(int k=j+1;k<cnt;k++)
   {
    if(rule1(c[i],c[j],c[k]))
    {
     type[0]++;
     continue;
    }
    if(rule2(c[i],c[j],c[k]))
    {
     type[1]++;
     continue;
    }
    if(rule3(c[i],c[j],c[k]))
    {
     type[2]++;
     continue;
    }
    int p=rule45678(c[i],c[j],c[k]);
    type[p]++;
   }
  }
 }
 for(int i=0;i<9;i++)
 {
  cout<<type[i]<<" ";
 }
}
发布了24 篇原创文章 · 获赞 5 · 访问量 270

猜你喜欢

转载自blog.csdn.net/qq_45639151/article/details/105141838