题意:斗地主啊斗地主。。。。已知你手上的牌和对手手上的牌,如果你出牌后对手不能
压你的牌或者他能压但是你手上已经没有牌,就输出Yes,否则输出No。
算法:
先判断能不能一次走完,然后模拟能赢的情况。
==========>逗逼回忆录
之前一直思路挺混乱的= =因为只对每张不同的牌计数了,而没有把相同张数的牌的种类进行计数。
所以后来无论是判断一次走完的情况还是如何枚举能获胜都无从下手。
另外判断顺序也没想清楚是先从王炸、炸弹、顺子、对子、单个来判断。
还是弱爆了=。=好惭愧~~~~~~~~
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char p[] = {'3','4','5','6','7','8','9','T','J','Q','K','A','2','X','Y'};
int c1[20],c2[20],num1[5],num2[5];
void Count(int x,int *num) // 对张数相同的牌的种类进行计数
{
if(x==1) num[1]++; // 张数为1的
else if(x==2) num[2]++; // 张数为2的
else if(x==3) num[3]++; // 张数为3的
else if(x==4) num[4]++; // 张数为4的
}
int solve(int n)
{
if(n==1) return 1;
else if(n==2 && num1[2]) return 1;
else if(n==2 && c1[13] && c1[14]) return 1;
else if(n==3 && num1[3]) return 1;
else if(n==4 && (num1[4] || (num1[3] && num1[1]))) return 1;
else if(n==5 && num1[3] && num1[2]) return 1;
else if(n==6 && num1[4]) return 1;
else return 0;
}
int main()
{
int T;
char str1[20],str2[20];
scanf("%d",&T);
while(T--)
{
scanf("%s%s",str1,str2);
int l1 = strlen(str1);
int l2 = strlen(str2);
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for(int i=0;i<l1;i++)
{
for(int j=0;j<15;j++)
{
if(str1[i]==p[j]) //对每种牌的张数进行计数
c1[j]++;
}
}
for(int i=0;i<l2;i++)
{
for(int j=0;j<15;j++)
{
if(str2[i]==p[j])
c2[j]++;
}
}
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
for(int i=0;i<15;i++)
{
Count(c1[i],num1);
Count(c2[i],num2);
}
int flag = 0;
if(l1<=6) // 能一次出完的情况
flag = solve(l1);
if(flag)
{
puts("Yes");
continue;
}
if(c1[13] && c1[14]) // 虽然不能一次出完但是我手里有王炸的情况
{
puts("Yes");
continue;
}
if(c2[13] && c2[14]) // 对方手里有王炸
{
puts("No");
continue;
}
if(num1[4]) //我手里有炸弹
{
int a=-1,b=-1;
for(int i=14;i>=0;i--)
{
if(c1[i]==4)
{
a = i;
break;
}
}
for(int i=14;i>=0;i--)
{
if(c2[i]==4)
{
b = i;
break;
}
}
if(a>b) //如果我的炸弹比对手大或者我有他没有
flag = 1;
if(b>a) //他的炸弹比我大
flag = -1;
}
if(flag == 1)
{
puts("Yes");
continue;
}
if(flag==-1) //当他的炸弹比我大时,无论我出什么都不可能赢他
{ //因为我一次出完和有王炸的情况已经在前面排除
puts("No");
continue;
}
if(num2[4]) //只有对手有炸弹
{
puts("No");
continue;
}
if(num1[3]) //我有顺子
{
int a = -1,b = -1;
for(int i=14;i>=0;i--)
{
if(c1[i]==3)
{
a = i;
break;
}
}
for(int i=14;i>=0;i--)
{
if(c2[i]==3)
{
b = i;
break;
}
}
if(num1[2] && !num2[2]) //由于规则是顺子只能带两张一样的牌或者一张牌
flag = 1; //所以如果我有两张一样的牌(对子),而他没有,他就不能压我的牌
if(a>b) //我的顺子比他大
flag = 1;
}
if(num1[2]) //对子
{
int a = -1,b = -1;
for(int i=14;i>=0;i--)
{
if(c1[i]==2 || c1[i]==3) //只要有>=2张的都可以拆成对子出,由于炸弹很厉害,所以不会拆成对出
{
a = i;
break;
}
}
for(int i=14;i>=0;i--)
{
if(c2[i]==2 || c2[i]==3)
{
b = i;
break;
}
}
if(a>=b)
flag = 1;
}
if(num1[1]) //单张
{
int a = -1,b = -1;
for(int i=14;i>=0;i--)
{
if(c1[i])
{
a = i;
break;
}
}
for(int i=14;i>=0;i--)
{
if(c2[i])
{
b = i;
break;
}
}
if(a>=b)
flag = 1;
}
if(flag)
puts("Yes");
else puts("No");
}
return 0;
}