程序设计Week9——B-东东学打牌

B-东东学打牌

    • 题目描述
    • Input
    • Output
    • 解题思路
    • 实现代码
    • 总结

题目描述

打牌,只考虑牌的数值,不考虑花色,每个人五张手牌,每种牌数量无限,手牌大小比较规则:
程序设计Week9——B-东东学打牌_第1张图片
序号越大,牌越大,在得知全场人手牌的情况下,按照手牌的大小,升序输出一个排行榜,牌大小相同时,名字字典序小的在前。

Input

输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。

Output

对于每组测试数据,输出 n 行,即这次全场人的排名。

解题思路

1.建立合适的结构体用于存储每个人的手牌和姓名信息;
2.读入字符串,一行一个人,将手牌的字符串形式转换为整数形式,易于比较;
3.根据题目要求,判断牌型大小,先判断顺子、龙顺和大牌,因为这三种是没有相同的点数的;再根据相同点数的牌的数量,依次判断牌型,这里判断时,我提前对手牌进行了一次排序,这样在判断时思路会更清晰,不容易漏掉情况,具体的手牌判断形式见代码注释;
4.最后根据手牌牌型的大小关系定义重载比较符号,再利用sort排序,输出即可。

实现代码

#include
#include
#include
using namespace std;

struct Card
{
	string name,s2;
	int c[5];
	int dui,dui2[2],san,san2[2],boom,shun,dro_shun,last;
	Card();
	void change();
	void judge();
	bool operator<(const Card &p) const;
};

Card::Card()
{
	dui=0;
	dui2[0]=0;
	dui2[1]=0;
	san=0;
	san2[0]=0;
	san2[1]=0;
	boom=0;
	shun=0;
	dro_shun=0;
	last=0;
}

void Card::change()
{
	int index=0;
	for(int i=0;i<s2.size();++i)
	{
		if(s2[i]=='A')
		{
			c[index]=1;
			index++;
		}
		else if(s2[i]=='1')
		{
			c[index]=10;
			index++;
			i++;
		}
		else if(s2[i]=='J')
		{
			c[index]=11;
			index++;
		}
		else if(s2[i]=='Q')
		{
			c[index]=12;
			index++;
		}
		else if(s2[i]=='K')
		{
			c[index]=13;
			index++;
		}
		else
		{
			c[index]=s2[i]-'0';
			index++;
		}
	}
}

void Card::judge()
{
	sort(c,c+5);
	if((c[1]+1==c[2])&&(c[2]+1==c[3])&&(c[3]+1==c[4]))
	{//后四张顺 
		if(c[0]+1==c[1])
			shun=c[4];		//常规顺子 
		else if(c[4]==13&&c[0]==1)
			dro_shun=1;		//龙顺 
		else if(c[0]==c[1])
		{
			dui=c[0];
			last=c[2]+c[3]+c[4];
		}
		else
			last=c[0]+c[1]+c[2]+c[3]+c[4];
	}
	else
	{
		if(c[0]==c[1])
		{//已经有两张一样的 
			if(c[1]==c[2])
			{//已经有三张一样的 
				if(c[2]==c[3])
				{//四张一样,炸弹
					boom=c[0];
					last=c[4]; 
				}
				else if(c[3]==c[4])
				{//c[0]=c[1]=c[2]
					san2[0]=c[0];
					san2[1]=c[3];
				}
				else
				{//c[0]=c[1]=c[2]
					san=c[0];
					last=c[3]+c[4];
				}
			}
			else if(c[2]==c[3])
			{//现在是两对 
				if(c[3]==c[4])
				{//c[0]=c[1]
					san2[0]=c[2];
					san2[1]=c[0];
				}
				else
				{//c[0]=c[1]
					dui2[0]=c[0];
					dui2[1]=c[2];
					last=c[4];
				}
			}
			else if(c[3]==c[4])
			{//c[0]=c[1]
				dui2[0]=c[0];
				dui2[1]=c[3];
				last=c[2]; 
			}
			else
			{//c[0]=c[1]
				dui=c[0];
				last=c[2]+c[3]+c[4];
			}
		}
		else if(c[1]==c[2])
		{//两张一样的 
			if(c[2]==c[3])
			{//三张一样的 
				if(c[3]==c[4])
				{//c[0]
					boom=c[1];
					last=c[0]; 
				}
				else
				{//c[0]
					san=c[1];
					last=c[0]+c[4];
				}
			}
			else if(c[3]==c[4])
			{//c[0]
				dui2[0]=c[1];
				dui2[1]=c[3];
				last=c[0]; 
			}
			else
			{//c[0]
				dui=c[1];
				last=c[0]+c[3]+c[4];
			}
		}
		else if(c[2]==c[3])
		{//两张一样的 
			if(c[3]==c[4])
			{//c[0]
				san=c[2];
				last=c[0]+c[1]; 
			}
			else
			{//c[0]
				dui=c[2];
				last=c[0]+c[1]+c[4];
			}
		}
		else if(c[3]==c[4])
		{//c[0]
			dui=c[3];
			last=c[0]+c[1]+c[2];
		}
		else
		{//c[0]
			last=c[0]+c[1]+c[2]+c[3]+c[4]; 
		}
	}
}

bool Card::operator<(const Card &p) const
{
	if(dro_shun||p.dro_shun)
	{
		if(dro_shun!=p.dro_shun)
			return dro_shun>p.dro_shun;
		else
			return name<p.name;
	}
	if(shun||p.shun)
	{
		if(shun!=p.shun)
			return shun>p.shun;
		else
			return name<p.name;
	}
	if(boom||p.boom)
	{
		if(boom!=p.boom)
			return boom>p.boom;
		else if(last!=p.last)
			return last>p.last;
		else
			return name<p.name;
	}
	if(san2[0]||p.san2[0])
	{
		if(san2[0]!=p.san2[0])
			return san2[0]>p.san2[0];
		else if(san2[1]!=p.san2[1])
			return san2[1]>p.san2[1];
		else
			return name<p.name;
	}
	if(san||p.san)
	{
		if(san!=p.san)
			return san>p.san;
		else if(last!=p.last)
			return last>p.last;
		else
			return name<p.name;
	}
	if(dui2[1]||p.dui2[1])
	{
		if(dui2[1]!=p.dui2[1])
			return dui2[1]>p.dui2[1];
		else if(dui2[0]!=p.dui2[0])
			return dui2[0]>p.dui2[0];
		else if(last!=p.last)
			return last>p.last;
		else 
			return name<p.name;
	}
	if(dui||p.dui)
	{
		if(dui!=p.dui)
			return dui>p.dui;
		else if(last!=p.last)
			return last>p.last;
		else
			return name<p.name;
	}
	if(last||p.last)
	{
		if(last!=p.last)
			return last>p.last;
 		else
		 	return name<p.name;
	}
}

Card p[100010];

int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;++i)
	{
		cin>>p[i].name>>p[i].s2;
		p[i].change();
		p[i].judge();
	}
	sort(p,p+n);
	for(int i=0;i<n;++i)
		cout<<p[i].name<<endl;
	return 0;
} 

总结

本题思路与Week6的模拟是类似的,主要用合理的结构体来存储牌型信息,最重要的是合理的对牌型进行判断,剩下的就很简单了(除了比较费时间之外)。
这种题目思路要清晰,像牌型判断这里,写的要有层次逻辑,要不然容易漏掉情况,debug还会很折磨。

你可能感兴趣的:(程序设计Week9——B-东东学打牌)