【20200327程序设计思维与实践 限时大模拟】掌握魔法の东东 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 种牌型中,每种牌型的方案数。


思路

考虑到最大数据量为(4×25)5=1010,直接用暴力穷举。

将除两张手牌以外的所有牌加入牌堆,用3重循环取出所有的组合(跳过重复)并进行判断。

先对牌的大小进行排序,以便大小比较,然后在8个if…else if…分支中进行判断:
若5张牌花色相同,且数值大小为依此增1的关系,则a[1]++;
否则,若数值大小为依此增1的关系,则a[2]++;
否则,若花色相同,则a[3]++;
否则,若4张牌大小相等,则a[4]++;
否则,若3张大小相等,另外2张大小相等,则a[5]++;
否则,若2张大小相等,另外2张大小相等,则a[6]++;
否则,若3张大小相等,则a[7]++;
否则,若2张大小相等,则a[8]++。
a[9]即所有余下牌型数目。


总结

最初的思路是分析每种牌型的特征,根据手牌的符合关系列出每种牌型的数量公式。写了许多行后意识到过于复杂,可能思路有问题。

重新思考解法,因为花色有1~5种,决定在最初思路的基础上分花色数目讨论,来使分类更清晰。再次尝试后依然过于复杂,遇到困难。

再次反思,考虑到数据规模,最终决定尝试直接暴力穷举,顺利AC。

回想心路历程,意识到自己还是缺乏编程解决问题的思维,日后吸取教训。


代码

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

struct CARD{
	int val;
	int suit;
	
	bool operator==(CARD& c){
		if(val==c.val&&suit==c.suit)return 1;
		else return 0;
	}
};

int A,B;
int a1,b1,a2,b2;
int ans[10];//储存9种牌型数量 
int a[7];//排序辅助数组 
int i1,i2,i3;
CARD c1,c2;
CARD c[101];

bool is1(){
	if(c1.suit==c2.suit&&c2.suit==c[i1].suit&&c[i1].suit==c[i2].suit&&c[i2].suit==c[i3].suit){
		if(a[5]-a[1]==4)return 1;
		else return 0;
	}
	else return 0;
}

bool is2(){
	if(a[2]-a[1]==1&&a[3]-a[2]==1&&a[4]-a[3]==1&&a[5]-a[4]==1)return 1;
	else return 0;
}

bool is3(){
	if(c1.suit==c2.suit&&c2.suit==c[i1].suit&&c[i1].suit==c[i2].suit&&c[i2].suit==c[i3].suit)return 1;
	else return 0;
}

bool is4(){
	if(a[4]==a[1]||a[5]==a[2])return 1;
	else return 0;
}

bool is5(){
	if((a[1]==a[3]&&a[4]==a[5])||(a[1]==a[2]&&a[3]==a[5]))return 1;
	else return 0;
}

bool is6(){
	if(a[1]==a[2]){
		if(a[3]==a[4]||a[4]==a[5])return 1;
		else return 0;
	}
	else if(a[2]==a[3]&&a[4]==a[5])return 1;
	else return 0;
}

bool is7(){
	if((a[1]==a[2]&&a[2]==a[3])||(a[2]==a[3]&&a[3]==a[4])||(a[3]==a[4]&&a[4]==a[5]))return 1;
	else return 0;
}

bool is8(){
	if(a[1]==a[2]||a[2]==a[3]||a[3]==a[4]||a[4]==a[5])return 1;
	else return 0;
}


int main(){
	cin>>A>>B;
	cin>>a1>>b1>>a2>>b2;
	
	c1.suit=b1;
	c1.val=a1;
	c2.suit=b2;
	c2.val=a2;
	
	int cot=0;
	for(int i=0;i<B;i++){
		for(int j=0;j<A;j++){
			if((i!=b1||j!=a1)&&(i!=b2||j!=a2)){//向牌堆中加入c1、c2外所有牌 
				c[cot].val=j;
	    		c[cot].suit=i;
    			cot++;
  			}
		}
	}
	
	
	int cot2=0;
	for(i1=0;i1<cot;i1++){
		for(i2=i1+1;i2<cot;i2++){
			for(i3=i2+1;i3<cot;i3++){//穷举所有组合 
				a[1]=c1.val;
        		a[2]=c2.val;
        		a[3]=c[i1].val;
        		a[4]=c[i2].val;
        		a[5]=c[i3].val;
        		sort(a+1,a+6);//预处理排序 
        		
        		//判断牌型 
				if(is1())ans[1]++;
				else if(is2())ans[2]++;
				else if(is3())ans[3]++;
				else if(is4())ans[4]++;
				else if(is5())ans[5]++;
				else if(is6())ans[6]++;
				else if(is7())ans[7]++;
				else if(is8())ans[8]++;
				
				cot2++;
			}
		}
	}
	ans[9]=cot2;
	for(int i=1;i<9;i++)ans[9]-=ans[i];
	for(int i=1;i<=9;i++)cout<<ans[i]<<" ";
	cout<<endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值