Week6 限时大模拟 掌握魔法的东东2

题目描述

在这里插入图片描述
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 种牌型的方案数(按牌型编号从小到大的顺序)。

样例

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

思路分析

这其实是一个子集枚举问题,在两个元素已经确定的情况下,枚举所有元素个数为5的子集,并判断类型。Dfs+可行性剪枝。

结构体card存储牌的大小和花色,排序方式为先按大小升序,再按花色升序。结构体数组p存放被选中的五张牌,先判断是否是1、2、3种类型并返回对应值。否则,剩下的几种类型主要是相等的牌数不同,定义整型变量num表示五张牌中不同数字的个数,初值为5;tag为当前已经连续相等的牌数,初值为1(若比较的两张牌不等则重置为1;max为五张牌中最大连续相等的牌数(if(tag>max)max=tag)。

if(num==5)  全不相等
if(num==4)  一对
if(num==3&&max==2)两对
if(num==3&&max==3)三条
if(num==2&&max==4)炸弹
if(num==2&&max==3)三代二

AC代码

#include<iostream>
#include<algorithm>
using namespace std;
int A,B,a1,b1,a2,b2; 
int chose[10]={0};// 
struct card
{
 int a,b;
 card(){};
 bool operator<(const card &c) const
    {//先按大小升序,再按花色升序 
        if(a!=c.a) return a<c.a;
        else
            return b<c.b;
    }
};
card c[100];//最多一百张牌 
card p[5];//五张被选中的牌 
void judge(card p[])
{
 /*for(int i=0;i<5;i++)
 {
  cout<<"pai"<<p[i].a<<" "<<p[i].b<<endl;
 }*/
 bool same=true;
 for(int i=0;i<4;i++)
 {
  if(p[i].b!=p[i+1].b)
  {
   same=false;
   break;
  }  
 }
 bool add=true;
 for(int i=0;i<4;i++)
 {
  if((p[i].a+1)!=p[i+1].a)
  {
   add=false;
   break;
  }  
 }
 if(same==true&&add==true) 
 {
  chose[1]++;
  return;
 }
 if(same)
 {
  chose[3]++;
  return;
 }
 if(add)
 {
  chose[2]++;
  return;
 }
 int num=5;//5张牌中的不同数字 数 
 int max=1,tag=1;
 for(int i=0;i<4;i++)
 {
  if(p[i].a==p[i+1].a)
  {
   tag++;
   num--;
   if(tag>max) max=tag;
  } 
  else{
   tag=1;
  }  
 }
 if(num==5)
 {
  chose[9]++;
 }//全部不相等 
 if(num==4)
 {
  chose[8]++;
 }//有一对相等
 if(num==3&&max==2)
 {
  chose[6]++;
 }
 if(num==3&&max==3)
 {
  chose[7]++;
 } 
 if(num==2&&max==4)
 {
  chose[4]++;
 }
 if(num==2&&max==3)
 {
  chose[5]++;
 }
 } 
void dfs(int count,int tag)
{
 //cout<<"count "<<count<<endl; 
 if(count==5)
 {
  card p1[5];
  for(int i=0;i<5;i++)
  {
   p1[i].a=p[i].a;
   p1[i].b=p[i].b;
  }
  sort(p1,p1+5);//排序
  judge(p1);
  return;
 }
 for(int i=tag;i<A*B;i++)
 {
  if((c[i].a==a1&&c[i].b==b1)||(c[i].a==a2&&c[i].b==b2)) continue;
  p[count].a=c[i].a;
  p[count].b=c[i].b;
  //cout<<"第"<<count+1<<"张牌"<<c[i].a<<" "<<c[i].b<<endl;
  dfs(count+1,i+1);
 }
}
int main()
{
 cin>>A>>B;
 cin>>a1>>b1>>a2>>b2;
 int index=0;
 for(int i=0;i<A;i++)
 {
  for(int j=0;j<B;j++)
  {
   c[index].a=i;
   c[index].b=j;
   index++;
  }
  } 
 int count=2;//初始牌数等于2
 p[0].a=a1;p[0].b=b1;
 p[1].a=a2;p[1].b=b2;
 dfs(count,0); 
 for(int i=1;i<=9;i++)
 {
  cout<<chose[i]<<" ";
 }
 return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rwyoi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值