hdu4930Fighting the Landlords(直接枚举)

题目:hdu4930Fighting the Landlords(直接枚举)


题目大意:给你两手牌,前面的是你的牌。问仅仅当前这一轮,你手中的牌可以赢吗?

赢的条件:你手中的牌出完了,或者是你出的牌对方要不起。这里的规则和斗地主的基本是一致的,只是没有顺子。规则就不详述了。


解题思路:总共最多就17张牌,先判断是否有双飞,有就获胜。然后将每种不同种类的牌(单支和对子算不同种类)的最大的牌找出来,同等级比较一下看能否取胜。还要注意看对方是否有双飞或是炸弹。最后还要判断自己的这一手牌能否出完,可以也取胜。这些都不可能取胜,那么就失败了。


代码:

#include <cstdio>
#include <cstring>

const int N = 20;

int v1[N], v2[N];
int l1 ,l2;
int type1[N], type2[N];//用来记录各种牌的最大值
char c1[N];//自己的牌
char c2[N];//对方的牌


int translate (char ch) {

	if (ch >= '3' && ch <= '9')
		return ch - '0';
	switch (ch) {

		case 'T' : return 10;
		case 'J' : return 11;
		case 'Q' : return 12;
		case 'K' : return 13;
		case 'A' : return 14;
		case '2' : return 15;
		case 'X' : return 16;
		case 'Y' : return 17;
	}
}

void cut (char *c, int * v) {//分解

	int n;
	for (int i = 0; i < strlen(c); i++) {

		n = translate(c[i]);
		v[n]++;
	}

}

int Max (int k, int num) {//找num个相同牌的最大值

	if (k == 0) {
		for (int i = 17; i >= 3; i--)
			if (v1[i] >= num) //注意是大于等于
				return i;	

	} else {
		for (int i = 17; i >= 3; i--) 
			if (v2[i] >= num) 
				return i;
	}
	return 0;
}

int Max_1 (int k, int num, int tail) {//找3带1或是3带2的情况

	if (k == 0) {
		for (int i = 17; i >= 3; i--)
			if (v1[i] >= num) {
				for (int j = 17; j >= 3; j--)
					if (j != i && v1[j] >= tail)
						return i;
			}

	} else {
		for (int i = 17; i >= 3; i--)
			if (v2[i] == num) {
				for (int j = 17; j >= 3; j--)
					if (j != i && v2[j] >= tail)
						return i;
			}
	}
	return 0;
}

bool is_empty () {  //判断能否走完

	if (l1 == 6 && type1[0])
		return true;
	if (l1 == 5 && type1[3])
		return true;
	if (l1 == 4 && (type1[0] || type1[2]))
		return true;
	if (l1 == 3 && type1[1])
		return true;
	if (l1 == 2 && type1[4])
		return true;
	if (l1 == 1)
		return true;
	return false;
}

bool solve () {

	memset (type1, -1, sizeof (type1));
	memset (type2, -1, sizeof (type2));
	l1 = strlen (c1);
	l2 = strlen (c2);

	//双飞
	if (v1[16] && v1[17])
		return true;
	//炸弹
	type1[0] = Max (0, 4);		
	type2[0] = Max (1, 4);
	if (type1[0] > type2[0] && !(v2[16] && v2[17]))
		return true;
	//3带0
	type1[1] = Max (0, 3);
	type2[1] = Max (1, 3); 	
	if (type1[1] > type2[1] && !(v2[16] && v2[17]) && !type2[0])
		return true;
	//3带1
	type1[2] = Max_1 (0, 3, 1);
	type2[2] = Max_1 (1, 3, 1);
	if (type1[2] > type2[2] && !(v2[16] && v2[17]) && !type2[0])
		return true;
	//3带2
	type1[3] = Max_1 (0, 3, 2);
	type2[3] = Max_1 (1, 3, 2);
	if (type1[3] > type2[3] && !(v2[16] && v2[17]) && !type2[0])
		return true;
	//对子
	type1[4] = Max (0, 2);
	type2[4] = Max (1, 2);
	if (type1[4] > type2[4] && !(v2[16] && v2[17]) && !type2[0])
		return true;
	//单枝
	type1[5] = Max (0, 1);
	type2[5] = Max (1, 1);
	if (type1[5] > type2[5] && !(v2[16] && v2[17]) && !type2[0])
		return true;
	//能否走完
	if (is_empty())
		return true;
	return false;

}

int main () {

	int t;
	scanf ("%d", &t);
	while (t--) {

		scanf ("%s%s", c1, c2);

		memset (v1, 0, sizeof (v1));
		memset (v2, 0, sizeof (v2));
		cut (c1, v1);
		cut (c2, v2);

		printf ("%s\n", solve()? "Yes": "No");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值