题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4930
题意:虽然题目很长,但是其实就是一直在介绍我们很熟悉的斗地主规则。要求这一轮里是否A出牌后B没有牌可以压过A。
解题思路:这道题尤其要注意出牌的先后性,先处理先手一方的情况,因为它是先出牌的一方。如果先手(A)有王炸的优先级是最高的,最先处理这种情况,直接输出Yes。然后处理先手可以一次性打完手里的牌的情况,这种情况也是不用考虑后手(B)的情况直接输出Yes即可。
然后考虑其他的情况,即先手无法直接秒杀后手的情况,此时要具体考虑后手的牌的情况。这时后手里是否有王炸的优先级是最高的,如果有王炸直接输出No即可。然后我们处理B中有炸弹的情况,因为炸弹可以攻击任意的除了王炸外的出牌,比较AB中炸弹的大小(如果存在),如果B的炸弹大于A或者A没有炸弹,则B此轮压过A,输出No。如果B没有炸弹,进行下面的步骤:再接下来细分各种出牌的组合可能性,对应地一一比较大小,如果A有任一出牌组合大于B,则输出Yes,然后结束算法。因为A是先手,它有出牌的主动权,所以只要有任意一种出牌方式B没法接,即可打出这种方式,那么B一定没有牌可以接,故输出Yes。
AC代码:
/*****************************************
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' | |// `.
/ ||| : |||// \
/ _||||| -:- |||||- \
| | \\ - /// | |
| _| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- `.;`\ _ /`;.`/ - ` : | |
\ \ `-. _ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
佛祖保佑 永无BUG
*****************************************/
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
map<char,int> m;
map<char,int> cnt1;
map<char,int> cnt2;
int main()
{
m['3'] = 1;
m['4'] = 2;
m['5'] = 3;
m['6'] = 4;
m['7'] = 5;
m['8'] = 6;
m['9'] = 7;
m['T'] = 8;
m['J'] = 9;
m['Q'] = 10;
m['K'] = 11;
m['A'] = 12;
m['2'] = 13;
m['X'] = 14;
m['Y'] = 15;
int t;
scanf("%d", &t);
char str1[20];
char str2[20];
while (t--)
{
cnt1.clear();
cnt2.clear();
scanf("%s %s", str1, str2);
int len1 = strlen(str1);
int len2 = strlen(str2);
for (int i = 0; i < len1; i++) cnt1[str1[i]]++;
for (int i = 0; i < len2; i++) cnt2[str2[i]]++;
if (cnt1['X'] && cnt1['Y'])
{
puts("Yes");
continue;
}
//直接能打完获胜
//1.单个
if (len1 == 1)
{
puts("Yes");
continue;
}
//2.对子
if (len1 == 2 && str1[0] == str1[1])
{
puts("Yes");
continue;
}
//3.3连
if (len1 == 3 && cnt1[str1[0]] == 3)
{
puts("Yes");
continue;
}
//4.三带一
if (len1 == 4)
{
bool ok = false;
for (int i = 0; i < len1; i++)
{
if (cnt1[str1[i]] >= 3)
{
ok = true;
break;
}
}
if (ok)
{
puts("Yes");
continue;
}
}
//5.三带二同
if (len1 == 5)
{
bool ok = false;
for (int i = 0; i < 5 && !ok; i++)
{
for (int j = 0; j < 5 && !ok; j++)
{
if (i == j) continue;
if (str1[i] != str1[j] && ((cnt1[str1[i]] == 2 && cnt1[str1[j]] == 3) || (cnt1[str1[i]] == 3 && cnt1[str1[j]] == 2)))
{
ok = true;
}
}
}
if (ok)
{
puts("Yes");
continue;
}
}
//6.四带二可不同
if (len1 == 6)
{
bool ok = false;
for (int i = 0; i < 6; i++)
{
if (cnt1[str1[i]] == 4)
{
ok = true;
break;
}
}
if (ok)
{
puts("Yes");
continue;
}
}
//7.王炸(已最先处理)
//8.炸弹(包在4中了)
//---------华丽丽的分割线---------//
int r1 = -1;
int r2 = -1;
if (cnt2['X'] && cnt2['Y'])
{
puts("No");
continue;
}
for (int i = 0; i < len2; i++)
{
if (cnt2[str2[i]] == 4)
{
r2 = max(r2,m[str2[i]]);
}
}
if (r2 != -1)
{
for (int i = 0; i < len1; i++)
{
if (cnt1[str1[i]] == 4)
{
r1 = max(r1,m[str1[i]]);
}
}
if (r1 < r2)//r1 == -1 || r1 < r2
{
puts("No");
continue;
}
}
//1.单个
r1 = -1;
r2 = -1;
for (int i = 0; i < len1; i++) r1 = max(r1,m[str1[i]]);
for (int i = 0; i < len2; i++) r2 = max(r2,m[str2[i]]);
if (r1 > r2)
{
puts("Yes");
continue;
}
//2.对子
if (len1 >= 2)
{
r1 = -1;
r2 = -1;
for (int i = 0; i < len1; i++)
{
if (cnt1[str1[i]] >= 2)
{
r1 = max(r1,m[str1[i]]);
}
}
if (r1 != -1 && len2 < 2)
{
puts("Yes");
continue;
}
for (int i = 0; i < len2; i++)
{
if (cnt2[str2[i]] >= 2)
{
r2 = max(r2,m[str2[i]]);
}
}
if (r1 > r2)
{
puts("Yes");
continue;
}
}
//3.3连
if (len1 >= 3)
{
r1 = -1;
r2 = -1;
for (int i = 0; i < len1; i++)
{
if (cnt1[str1[i]] >= 3)
{
r1 = max(r1,m[str1[i]]);
}
}
if (r1 != -1 && len2 < 3)
{
puts("Yes");
continue;
}
for (int i = 0; i < len2; i++)
{
if (cnt2[str2[i]] >= 3)
{
r2 = max(r2,m[str2[i]]);
}
}
if (r1 > r2)
{
puts("Yes");
continue;
}
}
//4.三带一
if (len1 >= 4)
{
r1 = -1;
r2 = -1;
for (int i = 0; i < len1; i++)
{
if (cnt1[str1[i]] == 3)
{
r1 = max(r1,m[str1[i]]);
}
}
if (r1 != -1 && len2 < 4)
{
puts("Yes");
continue;
}
for (int i = 0; i < len2; i++)
{
if (cnt2[str2[i]] == 3)
{
r2 = max(r2,m[str2[i]]);
}
}
if (r1 > r2)
{
puts("Yes");
continue;
}
}
//5.三带二同
if (len1 >= 5)
{
r1 = -1;
r2 = -1;
for (int i = 0; i < len1; i++)
{
for (int j = 0; j < len1; j++)
{
if (i == j) continue;
if (str1[i] != str1[j])
{
if (cnt1[str1[i]] == 3 && cnt1[str1[j]] == 2)
{
r1 = max(r1,m[str1[i]]);
}
if (cnt1[str1[i]] == 2 && cnt1[str1[j]] == 3)
{
r1 = max(r1,m[str1[j]]);
}
}
}
}
if (r1 != -1 && len2 < 5)
{
puts("Yes");
continue;
}
for (int i = 0; i < len2; i++)
{
for (int j = 0; j < len2; j++)
{
if (i == j) continue;
if (str2[i] != str2[j])
{
if (cnt2[str2[i]] == 3 && cnt2[str2[j]] == 2)
{
r2 = max(r2,m[str2[i]]);
}
if (cnt2[str2[i]] == 2 && cnt2[str2[j]] == 3)
{
r2 = max(r2,m[str2[j]]);
}
}
}
}
if (r1 > r2)
{
puts("Yes");
continue;
}
}
//6.四带二可不同
if (len1 >= 6)
{
r1 = -1;
r2 = -1;
for (int i = 0; i < len1; i++)
{
if (cnt1[str1[i]] == 4)
{
r1 = max(r1,m[str1[i]]);
}
}
if (r1 != -1 && len2 < 6)
{
puts("Yes");
continue;
}
for (int i = 0; i < len2; i++)
{
if (cnt2[str2[i]] == 4)
{
r2 = max(r2,m[str2[i]]);
}
}
if (r1 > r2)
{
puts("Yes");
continue;
}
}
//7.王炸
//8.炸弹
if (len1 >= 4)
{
r1 = -1;
r2 = -1;
for (int i = 0; i < len1; i++)
{
if (cnt1[str1[i]] == 4)
{
r1 = max(r1,m[str1[i]]);
}
}
if (r1 != -1 && len2 < 4)
{
puts("Yes");
continue;
}
for (int i = 0; i < len2; i++)
{
if (cnt2[str2[i]] == 4)
{
r2 = max(r2,m[str2[i]]);
}
}
if (r1 > r2)
{
puts("Yes");
continue;
}
}
puts("No");
}
return 0;
}