week-6-限时-掌握魔法の东东 II

题意

从瑞神家打牌回来后,东东痛定思痛,决定苦练牌技,终成赌神!
东东有 A × B 张扑克牌。每张扑克牌有一个大小(整数,记为a,范围区间是 0 到 A - 1)和一个花色(整数,记为b,范围区间是 0 到 B - 1。
扑克牌是互异的,也就是独一无二的,也就是说没有两张牌大小和花色都相同。
“一手牌”的意思是你手里有5张不同的牌,这 5 张牌没有谁在前谁在后的顺序之分,它们可以形成一个牌型。 我们定义了 9 种牌型,如下是 9 种牌型的规则,我们用“低序号优先”来匹配牌型,即这“一手牌”从上到下满足的第一个牌型规则就是它的“牌型编号”(一个整数,属于1到9):

同花顺: 同时满足规则 2 和规则 3.
顺子 : 5张牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
同花 : 5张牌都是相同花色的.
炸弹 : 5张牌其中有4张牌的大小相等.
三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
三条: 5张牌其中有3张牌的大小相等.
一对: 5张牌其中有2张牌的大小相等.
要不起: 这手牌不满足上述的牌型中任意一个.
现在, 东东从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 种牌型的方案数(按牌型编号从小到大的顺序)

	样例:
	Input
    5 2
    1 0 3 1
    Output
    0 8 0 0 0 12 0 36 0

思路

  • 由于数据范围比较小,这个题使用了暴力的方法,接下来就是分析如何暴力
  • 首先是得到五张互斥的手牌,这个过程可以通过三重循环去实现,在循环过程中,加入互斥判断条件,使得不会出现相同的牌;
  • 紧接着应该思考的一个问题就是如何去判断这五张牌属于哪一种牌,牌的类型有九种;
  • 我们可以发现同花,所有牌的颜色相同,那么我们就可以为每一张手牌加一个color_number(花色重复度),初始为1,如果出现花色相同的牌,那么这张牌的color_number+1;通过两次两重循环就可以知道所有的牌的color_number;
  • 另一个需要构建的是大小重复复value_number;如果出现相同的,那么就+1;
  • 所以存储手牌的是结构体数组,成员为 value,color,value_number(大小重复度),color_number(花色重复度);
  • 我们需要额外的三个数组,p1进行value值的<重载,pp进行color_number的<重载,ppp进行value_number的<重载;然后对这三个数组进行升序排序;
  • 同花,就是数组pp的最后一个元素的color_number=5;顺子就是p原数组的每一个元素加一都等于下一个元素;同花顺就是pp数组最后一个元素的color_number=5且p原数组的每一个元素加一都等于下一个元素;炸弹就是ppp数组最后一个元素的value_number=4;三代二就是ppp数组最后一个元素的value_number=3且第二个元素的value_number=2;两对就是ppp数组最后一个元素的value_number=2且第二个元素的value_number=2;三条是ppp数组最后一个元素的value_number=3且第二个元素的value_number=1;一对就是ppp数组最后一个元素的value_number=2,且第三个元素value_number=1;要不起就是不满足以上八种;
  • 每一个情况都有一个常量值在计数

总结

  • 此题就是获得手牌的时候要进行将一些错误的数据排除,就是不能出现互斥,所以使用三重循环,然后三重循环是递进的,下一重循环的起始点是上一重循环的起始点加1,这就能避免三次出现互斥,然后再每次循环都要和第一张和第二张手牌进行互斥判断;
  • 其次就是保留原数组,因为前两张牌是一直不变的;

代码

#include<iostream>
#include<algorithm>
using namespace std;
struct card {
	int value;
	int color;
	int value_number;//重复度
	int color_number;//重复度
	bool operator<(const card& x)
	{
		return value< x.value;
	}
	card& operator=(const card& x)
	{
		value = x.value;
		color = x.color;
		value_number= x.value_number;
		color_number = x.color_number;
		return *this;
	}
	bool operator!=(const card& x)
	{
		if (value != x.value)
			return true;
		if (color != x.color)
			return true;
		return false;
	}
};
struct card1 {
	int value1;
	int color1;
	int value_number1;//重复度
	int color_number1;//重复度
	card1& operator=(const card& x)
	{
		value1 = x.value;
		color1 = x.color;
		value_number1 = x.value_number;
		color_number1 = x.color_number;
		return *this;
	}
	bool operator<(const card1& x)
	{
		return color_number1 < x.color_number1;
	}
};
struct card2 {
	int value2;
	int color2;
	int value_number2;//重复度
	int color_number2;//重复度
	card2& operator=(const card& x)
	{
		value2 = x.value;
		color2 = x.color;
		value_number2 = x.value_number;
		color_number2 = x.color_number;
		return *this;
	}
	bool operator<(const card2& x)
	{
		return value_number2 < x.value_number2;
	}
};
card p[5];
int a[9];
int A=0, B=0;
void calculate()
{
	for(int i=0;i<5;i++)
		for (int j = 0; j < 5; j++)
		{
			if (p[i].color == p[j].color)
				p[i].color_number++;
			if (p[i].value == p[j].value)
				p[i].value_number++;
		}
}
void init()
{
	for (int i = 0; i < 5; i++)
	{
		p[i].color_number = 0;
		p[i].value_number = 0;
	}
}
void panduan()  //初始化
{
	card1 pp[5];//,
	card2 ppp[5];
	card p1[5];
	for (int i = 0; i < 5; i++)
		p1[i] = p[i];     //进行value的排序
	for (int i = 0; i < 5; i++)
	{
		pp[i] = p[i];  //进行color重复度的排序
	}
	for (int i = 0; i < 5; i++)
	{
		ppp[i] = p[i];  //进行value重复度的排序
	}
	sort(p1, p1 + 5);
	sort(pp, pp+ 5);
	sort(ppp, ppp + 5);
	if (pp[4].color_number1 == 5 && (p1[0].value + 1 == p1[1].value && p1[1].value + 1 == p1[2].value && p1[2].value + 1 == p1[3].value && p1[3].value + 1 == p1[4].value))
		a[0]++;
	else if (p1[0].value + 1 == p1[1].value && p1[1].value + 1 == p1[2].value && p1[2].value + 1 == p1[3].value && p1[3].value + 1 == p1[4].value)
		a[1]++;
	else if (pp[4].color_number1 == 5)
		a[2]++;
	else if (ppp[4].value_number2 == 4)
		a[3]++;//炸弹
	else if (ppp[4].value_number2 == 3 && ppp[1].value_number2 == 2)
		a[4]++;//三代二
	else if (ppp[4].value_number2 == 2 && ppp[1].value_number2 == 2)
		a[5]++;//两队
	else if (ppp[4].value_number2 == 3 && ppp[1].value_number2 == 1)
		a[6]++;//三条
	else if (ppp[4].value_number2 == 2 && ppp[2].value_number2 == 1)
		a[7]++;//一对;
	else
		a[8]++;//要不起;
	}

void get(int a1,int b1,int a2,int b2)
{
	int leng = A * B;
	card* m = new card[leng];
	int count = 0;
	for(int i=0;i<A;i++)
		for (int j = 0; j < B; j++)
		{
			m[count].value = i;
			m[count].color = j;
			count++;
		}
	for (int i = 0; i < A * B - 2; i++)
	{
		if (m[i]!=p[0]&&m[i]!=p[1])
		{
			for (int j = i+1; j < A * B - 1; j++)
			{
				if (m[j] != p[0] && m[j] != p[1])
				{
					for (int k = j+1; k < A * B; k++)
					{
						if (m[k] != p[0] && m[k] != p[1])
						{
							p[2] = m[i];
							p[3] = m[j];
							p[4] = m[k];
							init();
							calculate();
							panduan();
						}
					}
				}
			}
		}
	}
}
int main()
{
	
	cin >> A >> B;
	int a1, b1, a2, b2;
	cin >> a1 >> b1 >> a2 >> b2;
	p[0].value = a1;
	p[0].color = b1;
	p[1].value = a2;
	p[1].color = b2;
	get(a1,b1,a2,b2);
	for (int i = 0; i < 9; i++)
		cout << a[i] << " ";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值