程序设计思维与实践 Week6 限时大模拟

题意:

题目给定一个牌的数量以及每种牌的颜色数量。初始的时候,自己拿有两张牌,接下来在剩余的牌中再抽取三张,根据这五张牌的情况,问符合下面9种牌型的组合各有多少种。其中以低序号优先级来确定牌的组合种类。
在这里插入图片描述

input:

第一行整数A,B分别为牌的种类数量,每种牌的花色数量。第二行为分配给你的两张牌,分别为牌面大小和花色。
在这里插入图片描述
output:

输出一行,这行有 9 个整数,每个整数代表了 9 种牌型的方案数(按牌型编号从小到大的顺序)。

思路:

一开始的思路即为暴力枚举,和排列组合。觉得排列组合可能不需要什么算法的优化,于是选择的排列组合。然后就入坑了。程序写的很简单,没有什么算法方面的优化问题,主要就是排列组合的式子,就是觉得没什么毛病,但总有问题,还能过不少组数据,调了老长时间。没主要的几个需要注意的就是求同花顺,同花顺的时候, 先根据手中的两张牌,如果颜色不同,或者相差的值大于4,即不可能组成同花顺。在该情况符合条件下,可以从这两张牌组成的同花顺的上界或者下界来判断可以组成多少种同花顺。在这里以下界来判断,首先可以根据比较大的那张牌a2-4,得到同花顺的下界,当然注该下界如果小于0,则下界定位0。然后根据较小的那张牌a1来判定该同花顺的最小牌的上界,如果牌的数量A-4大于a1,则上界为a1,否则为A-4。最后根据上下界即可得到同花顺的种类。顺子的种类与其相似,要注意顺子和同花得到的数量要减去同花顺的种类数。其他的牌型因为该程序的实现的原因没啥算法方面的可说,主要就是排列组合的运用。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

long long A,B,a1,b1,a2,b2;
long long s[10];  //九种牌型


//同花顺 
void f1(){  
	if(b1!=b2 || a2-a1>4 ) return;
	if(a1==a2) return;	
	
    long long l = a2-4;
	if(l<0)  l=0;
    long long r = A-5;
	if(a1<r) r=a1;
    s[1]= r-l+1;
}; 


//顺子 
void f2(){
	if(a2-a1>4 || a1==a2)  return;
	
    long long l = a2-4;
	if(l<0)  l=0;
    long long r = A-5;
	if(a1<r) r=a1;

	s[2]=(r-l+1)*B*B*B-s[1];
}


//同花 
void f3(){
	if(b1!=b2) return;
	s[3]=(A-2)*(A-3)*(A-4)/6-s[1];
	
} 

/ 
void f4(){	
	if(B<4)  return;
	if(a1==a2){
		s[4]=(A-1)*B;
	}else{
		s[4]=2;
	}
}


//三带二 
void f5(){
	if(B<3) return;
    if(B==3)
    {
        if(a1==a2)
        {
            s[5]=(A-1)*3+A-1;
        }else s[5]=4;
    }
    
    if(B==4)
    {
        if(a1==a2) s[5]=(A-1)*4+2*(A-1)*6;
        else s[5]=18;
    }
}


//两对 
void f6(){
	if(B==1) return;
	if(a1==a2){
		s[6]=(A-1)*B*(B-1)*(A-2)*B/2;
			
	}else{
		s[6]=(B-1)*(B-1)*(A-2)*B +(B-1)*(A-2)*B*(B-1); 
	} 
}


//三条 
void f7(){
	if(B<3) return;
	if(a1==a2){
		s[7]=(B-2)*(A-1)*(A-2)*B*B/2;	
			
	}else{
		s[7]=(A-2)*B*(B-1)*(B-2)/6+(A-2)*B*(B-1)*(B-2);
		
	}	
}

//一对 
void f8(){
	if(B<2) return;
	if(a1==a2){
		s[8]=(A-1)*(A-2)*(A-3)*B*B*B/6; 
	}else{
		s[8]=(B-1)*(A-2)*B*(A-3)*B+ (A-2)*B*(B-1)*(A-3)*B/2;	
	} 
}

void f9(){
	s[9]=(A*B-2)*(A*B-3)*(A*B-4)/6;
	
	long long sum=0;
	for(int i=1; i<9;i++){
		sum+=s[i];
	}
	s[9]=s[9]-sum;
}


int main(){
	cin>>A>>B;
	cin>>a1>>b1>>a2>>b2;
	for(int i=1; i<10;i++){
		s[i]=0;
	}
	if(a1>a2){
		swap(a1,a2);
        swap(b1,b2);
	}
	
	f1();
	f2();
	f3();
	f4();
	f5();
	f6();	             
	f7();
	f8();
	f9();
		
	for(int i=1; i<10; i++){
		cout<<s[i]<<" ";
	} 
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值