程序设计思维与实践 Week9 B东东打牌

题意:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
input:

在这里插入图片描述
output:

对于每组测试数据,输出 n 行,即这次全场人的排名。
样例:
在这里插入图片描述
思路:

很明显是根据不同的牌的组合来得到一个分数,然后根据这个分数来进行一个关键字排序。在此处将关键字排序分为了三个:第一个关键字是手牌的8个类型,即按照给的手牌的分数,来依次给其score1赋上1到8分。第二个关键字是当手牌类型相同的时候,后续牌的大小不同来依次赋上score2相应的分数,例如对子中,首先比较对子大小,如果相同,即再比较剩下的三张牌的总和。在这里一开始考虑的是分情况讨论,想了挺久,觉得后期再总的排序有点麻烦,就给每个不同的重要性一个相应的权值。例如对子中,先比较对子大小,就先给对子的数值权值为100,乘上对子的牌的大小,后续的权值为1,这样权值大的有绝对的影响力。只有当前序的所有点都是一样的时候,后续的点才会起作用,对应上了比较的前后顺序,在这里给的每一阶权值都是100倍。第三个关键字即为姓名的字典序,可用string直接比较。
前期准备:一个1-13的数组tmp,分别记录5张牌有多少,然后tmp2记录是哪个五张牌,其中tot为牌种类数。根据牌的种类数,和每种牌有多少,可以依次得到属于哪一类,并根据数值,为其赋上相应的score1和score2。其中每个人的两个得分,手牌,姓名等,都是在结构体中,并重写了<,即可用sort进行排序,然后输出姓名即可。

代码:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int n;
priority_queue<int> Que;
int tmp[14];   //存放牌的种类

int tmp2[5];  //存放手牌的种类
int tot;

struct P{
	int score1, score2;
	string pai,name;
	bool operator<(const P &p) const{
		if(score1!=p.score1) return score1>p.score1;
		if(score2!=p.score2) return score2>p.score2; 
		return name<p.name;
	}
}Ps[100010];

int f(int t){
	memset(tmp,0,sizeof(tmp));
	memset(tmp2,0,sizeof(tmp2));
	tot=0;
	for(int i=0; i<Ps[t].pai.size(); i++){	
		if(Ps[t].pai[i]=='A'){        //65
			tmp[1]++;
		}else if(Ps[t].pai[i]=='1'){   //49
			tmp[10]++;
		}else if(Ps[t].pai[i]=='J'){  //74
			tmp[11]++;
		}else if(Ps[t].pai[i]=='Q'){   //81
			tmp[12]++;
		}else if(Ps[t].pai[i]=='K'){   //75
			tmp[13]++;
		}else{
			tmp[Ps[t].pai[i]-48]++;   
		}			
	}
	for(int i=1; i<=13; i++){
		if(tmp[i]!=0) {
			tmp2[tot]=i;  //记录了有哪些牌 
			tot++;
		}
	}
	
	int a=0;
	if(tot==5){  //五种牌 
		int N=0;
		int ret=-1; 
		for(int i=0; i<4; i++){
			if(tmp2[i+1]!=tmp2[i]+1){
				ret=1;
			}
		} 
		if(ret==-1){
			Ps[t].score1=7;  //顺子 
			Ps[t].score2=tmp2[4];
			N=1;
		}
		
		if(N==0){
			if(tmp2[0]==1){
				int ret=-1;
				for(int i=1; i<=4;i++){  //龙顺 
					if(tmp2[i]!=10+i-1){
						ret=1;
					}				
				}
				if(ret==-1){   
					Ps[t].score1=8;
					Ps[t].score2=0;
					N=1;
				}
			}
		}
		if(N==0){       //大牌 
			Ps[t].score1=1;
			for(int i=0; i<5; i++){
				Ps[t].score2+=tmp2[i];
			}
		}

		
	}else if(tot==4){   //对子 
		Ps[t].score1=2;
		for(int i=0; i<=3; i++){
			if(tmp[tmp2[i]]==2){
				Ps[t].score2+=tmp2[i]*100;
			}else{
				Ps[t].score2+=tmp2[i];
			}
		}
	}else if(tot==3){
		int M=0;
		for(int i=0; i<3; i++){
			if(M<tmp[tmp2[i]]) M=tmp[tmp2[i]];
		}
		if(M==2){  //两对
			Ps[t].score1=3;
			int j=100;
			for(int i=0; i<3;i++){
				if(tmp[tmp2[i]]==1){
					Ps[t].score2+=tmp2[i];
				}else{
					Ps[t].score2+=tmp2[i]*j;
					j*=100;	
				}
			}		
		}else{    //三个 
			Ps[t].score1=4;
			for(int i=0; i<3;i++){
				if(tmp[tmp2[i]]==1){
					Ps[t].score2+=tmp2[i];
				}else{
					Ps[t].score2+=tmp2[i]*100;
				}
			}	
		}
		
	}else{ 
		int M=0;
		for(int i=0; i<2; i++){
			if(M<tmp[tmp2[i]]) M=tmp[tmp2[i]];
		}
		if(M==4){ / 
			Ps[t].score1=6;
			for(int i=0; i<2; i++){
				if(tmp[tmp2[i]]==4){
					Ps[t].score2+=tmp2[i]*100;
				}else{
					Ps[t].score2+=tmp2[i];
				}
			}	
		}else{  //三带二 
			Ps[t].score1=5;
			for(int i=0; i<2; i++){
				if(tmp[tmp2[i]]==3){
					Ps[t].score2+=tmp2[i]*100;
				}else{
					Ps[t].score2+=tmp2[i];
				}
			}
			
		}	
	}
}

int main(){
	ios::sync_with_stdio(0);
	while(cin>>n){
		for(int i=0; i<n; i++){
			cin>>Ps[i].name>>Ps[i].pai;
			f(i);   //记录score1和score2 
		}
		sort(Ps,Ps+n);
		for(int i=0; i<n;i++){
			cout<<Ps[i].name<<endl;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值