2018.10.29【NOIP训练】7w523(模拟)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83513962

传送门


解析:

这是一个大家应该都 v a n van♂ 过的游戏(没玩过没关系,题目描述还是够清晰的了)。

所以整理一下思路,模拟题肯定要理清楚思路再下手,不然手忙脚乱很容易出错。

我分享一下我的思路:
首先这道模拟的主要对象就是玩家,所以我们可以封装一个结构体来实现玩家的各种操作。

发牌&补牌

首先是发牌,我们可以用一个 f l a g flag 记录这次是否是发的第一轮的庄家,然后额外发一张牌。

领取新的牌可以用一个函数 n x t c a r d nxtcard 来实现。
至于发牌怎么处理,由于题目要求不能拆对子和炸弹,所以我们直接用四个 s e t set 记录不同种类(单牌,对子,炸弹,氢弹)目前有哪些牌可以用。

我们可以用一个 i n s e r t insert 函数来实现新摸牌的操作,注意特判双王的情况。
新加的牌就是看它能否和原来的牌再凑一个更大的牌型。

头家出牌:

这个直接按照题意找一下什么牌能出就行了。
就是代码里面的 g o f i r s t gofirst 函数。

局中拼牌:

首先优先考虑碰的操作,判断是否是单牌,如果是,就在其他玩家手里找对应的对子,注意碰完之后为了方便, l a s t c a r d lastcard 的类型最好变成炸弹。

然后就是普通的拼大小。
这个可以直接用 s e t set 来一个upper_bound,然后考虑出炸弹,注意要考虑原本就是炸弹的情况。

游戏结束:

这个先判牌堆里面还有没有牌,然后判玩家手里还有没有就行了。

Detail:

1.注意时刻要更新玩家目前的手牌数,由于我是直接用牌的种类(单牌,对子,炸弹,氢弹)来判断出的牌数,所以要特殊处理一下双王的情况。

2.碰完之后还有一个情况需要处理,就是下家的改变,我就是这个写掉了两个字符就 W A WA 了几发。

接下来就是个人的耐心,细致和毅力以及码力的比拼了。


代码(无调试代码)(下面有一份有调试痕迹的):

#include<bits/stdc++.h>
using namespace std;
#define re register
#define cs const
typedef pair<int,int> pii; 
#define single  type[0]
#define pair    type[1]
#define boom    type[2]
#define bigboom type[3]

map<char,int> val;
char sss[1000],*cur=sss; 
inline int nxtcard(){return val[*(cur++)];}
inline bool nocard(){return val[*cur]==0;}

inline bool isking(int card){
	return card==13||card==14;
}

inline int anotherking(int king){
	return 27-king;
}

inline int cntcard(cs pii &a){
	if(a.second!=2)return a.second+1;
	if(a.first==13||a.first==14)return 2;
	else return 3;
}

bool flag=true;
struct players{
	int now;
	set<int> type[4];
	
	inline void insert(int card){//新摸一张 
		++now;
		for(int re i=2;~i;--i){
			if(type[i].find(card)!=type[i].end()){
				type[i+1].insert(card);
				type[i].erase(card);
				return;
			}
		}
		if(isking(card)){
			if(single.find(anotherking(card))!=single.end()){
				single.erase(anotherking(card));
				boom.insert(14);
			}
			else single.insert(card);
		}
		else{
			single.insert(card);
		}
	}
	
	inline void init(){//补牌 or 初始摸牌 
		while(now<5){
			int card=nxtcard();
			if(card==0)return;
			insert(card);
		}
		if(flag){
			flag=false;
			int card=nxtcard();
			if(card)insert(card);
		}
	}
	
	inline pii gofirst(){//第一个出牌 
		if(now==0)return make_pair(0,0);
		if(!pair.empty()&&*pair.begin()!=val['7']){
			int card=*pair.begin();
			pair.erase(pair.begin());
			now-=2;
			return make_pair(card,1);
		}
		if(!single.empty()){
			int card=*single.begin();
			single.erase(single.begin());
			now-=1;
			return make_pair(card,0);
		}
		if(!pair.empty()&&*pair.begin()==val['7']){
			int card=*pair.begin();
			pair.erase(pair.begin());
			now-=2;
			return make_pair(card,1);
		}
		if(!boom.empty()){
			int card=*boom.begin();
			boom.erase(boom.begin());
			if(card!=14&&card!=13)now-=3;
			else now-=2;
			return make_pair(card,2);
		}
		if(!bigboom.empty()){
			int card=*bigboom.begin();
			bigboom.erase(bigboom.begin());
			now-=4;
			return make_pair(card,3);
		}
	}
	
	inline pii peng(cs pii &a){
		if(pair.find(a.first)!=pair.end()){
			pair.erase(a.first);now-=2;
			return make_pair(a.first,1);
		}
		return make_pair(0,0);
	}
	
	inline pii compete(cs pii &cd){
		int ty=cd.second;
		int card=cd.first;
		set<int>::iterator it=type[ty].upper_bound(card);
		if(it!=type[ty].end()){
			card=*it;
			type[ty].erase(it);
			now-=cntcard(make_pair(card,ty));
			return make_pair(card,ty);
		}
		for(int re i=max(ty+1,2);i<=3;++i){
			if(!type[i].empty()){
				card=*type[i].begin();
				type[i].erase(type[i].begin());
				now-=cntcard(make_pair(card,i));
				return make_pair(card,i);
			}
		}
		return make_pair(0,0);
	}
	
	inline bool empty(){return now==0;}
}player[4];

int score[4];
int n,lastwinner=0,totcard;

inline bool gameend(){
	if(!nocard())return false;
	for(int re i=0;i<n;++i)if(player[i].empty())return true;
	return false;
}

signed main(){
	{//权值打表
		val[' ']=0;
		val[0]=0;
		val['\n']=0;
		val['4']=1;
		val['6']=2;
		val['8']=3;
		val['9']=4;
		val['X']=5;
		val['J']=6;
		val['Q']=7;
		val['K']=8;
		val['A']=9;
		val['3']=10;
		val['2']=11;
		val['5']=12;
		val['F']=13;
		val['G']=14;
		val['7']=15;
	}
	scanf("%d",&n);
	scanf("%s",sss);
	
	while(true){
		totcard=0;
		for(int re i=0;i<n;++i)player[(i+lastwinner)%n].init();
		if(gameend())break;
		pii lastcard=player[lastwinner].gofirst();
		totcard+=cntcard(lastcard);
		if(lastcard.second==0){
			for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
				pii nowcard=player[i].peng(lastcard);
				if(nowcard.first==0)continue;
				lastcard=nowcard;
				totcard+=cntcard(nowcard);
				lastwinner=i;
				lastcard.second=2;
				break;
			}
		}
		for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
			pii nowcard=player[i].compete(lastcard);
			if(nowcard.first==0)continue;
			lastwinner=i;
			totcard+=cntcard(nowcard);
			lastcard=nowcard;
			if(lastcard.second==0){
				for(int re j=(lastwinner+1)%n;j!=lastwinner;j=(j+1)%n){
					pii nowcard=player[j].peng(lastcard);
					if(nowcard.first==0)continue;
					lastcard=nowcard;
					totcard+=cntcard(nowcard);
					i=lastwinner=j;
					lastcard.second=2;
					break;
				}
			}
		}
		score[lastwinner]+=totcard;
	}
	for(int re i=0;i<n;++i)printf("%d\n",score[i]+player[i].now);
	return 0;
}

代码(保留调试痕迹):

#include<bits/stdc++.h>
using namespace std;
#define re register
#define cs const
typedef pair<int,int> pii; 
#define single  type[0]
#define pair    type[1]
#define boom    type[2]
#define bigboom type[3]

map<char,int> val;
char sss[1000],*cur=sss; 
inline int nxtcard(){return val[*(cur++)];}
inline bool nocard(){return val[*cur]==0;}

inline bool isking(int card){
	return card==13||card==14;
}

inline int anotherking(int king){
	return 27-king;
}

inline int cntcard(cs pii &a){
	if(a.second!=2)return a.second+1;
	if(a.first==13||a.first==14)return 2;
	else return 3;
}

bool flag=true;
struct players{
	int now;
	set<int> type[4];
	
	inline void insert(int card){//新摸一张 
		++now;
		for(int re i=2;~i;--i){
			if(type[i].find(card)!=type[i].end()){
				type[i+1].insert(card);
				type[i].erase(card);
				return;
			}
		}
		if(isking(card)){
			if(single.find(anotherking(card))!=single.end()){
				single.erase(anotherking(card));
				boom.insert(14);
			}
			else single.insert(card);
		}
		else{
			single.insert(card);
		}
	}
	
	inline void init(){//补牌 or 初始摸牌 
		while(now<5){
			int card=nxtcard();
			if(card==0)return;
			insert(card);
		}
		if(flag){
			flag=false;
			int card=nxtcard();
			if(card)insert(card);
		}
	}
	
	inline pii gofirst(){//第一个出牌 
		if(now==0)return make_pair(0,0);
		if(!pair.empty()&&*pair.begin()!=val['7']){
			int card=*pair.begin();
			pair.erase(pair.begin());
			now-=2;
			return make_pair(card,1);
		}
		if(!single.empty()){
			int card=*single.begin();
			single.erase(single.begin());
			now-=1;
			return make_pair(card,0);
		}
		if(!pair.empty()&&*pair.begin()==val['7']){
			int card=*pair.begin();
			pair.erase(pair.begin());
			now-=2;
			return make_pair(card,1);
		}
		if(!boom.empty()){
			int card=*boom.begin();
			boom.erase(boom.begin());
			if(card!=14&&card!=13)now-=3;
			else now-=2;
			return make_pair(card,2);
		}
		if(!bigboom.empty()){
			int card=*bigboom.begin();
			bigboom.erase(bigboom.begin());
			now-=4;
			return make_pair(card,3);
		}
	}
	
	inline pii peng(cs pii &a){
		if(pair.find(a.first)!=pair.end()){
			pair.erase(a.first);now-=2;
			return make_pair(a.first,1);
		}
		return make_pair(0,0);
	}
	
	inline pii compete(cs pii &cd){
		int ty=cd.second;
		int card=cd.first;
		set<int>::iterator it=type[ty].upper_bound(card);
		if(it!=type[ty].end()){
			card=*it;
			type[ty].erase(it);
			now-=cntcard(make_pair(card,ty));
			return make_pair(card,ty);
		}
		for(int re i=max(ty+1,2);i<=3;++i){
			if(!type[i].empty()){
				card=*type[i].begin();
				type[i].erase(type[i].begin());
				now-=cntcard(make_pair(card,i));
				return make_pair(card,i);
			}
		}
		return make_pair(0,0);
	}
	
	inline bool empty(){return now==0;}
}player[4];

int score[4];
int n,lastwinner=0,totcard;

inline bool gameend(){
	if(!nocard())return false;
	for(int re i=0;i<n;++i)if(player[i].empty())return true;
	return false;
}

string typ[4]={(string)"单牌",(string)"对子",(string)"炸弹",(string)"氢弹"}; 
char car[50]={'?','4','6','8','9','X','J','Q','K','A','3','2','5','F','G','7'};

inline void debug(int play,cs pii &card){
	cerr<<"player "<<lastwinner<<" 出牌 "<<typ[card.second]<<" "<<car[card.first];
	cerr<<" 剩余手牌 "<<player[play].now<<" 张\n"; 
}

inline void Debug(){
	for(int re i=0;i<n;++i){
		cerr<<"player "<<i<<" :";
		if(player[i].empty()){
			cerr<<"\nno cards\n";
			continue;
		}
		for(int re j=0;j<4;++j){
			if(player[i].type[j].empty())continue;
			cerr<<"\n"<<typ[j]<<" : ";
			for(set<int>::iterator it=player[i].type[j].begin();it!=player[i].type[j].end();++it){
				cerr<<car[*it]<<" ";
			}
			cerr<<"\n";
		}
	}
}

signed main(){
	{//权值打表
		val[' ']=0;
		val[0]=0;
		val['\n']=0;
		val['4']=1;
		val['6']=2;
		val['8']=3;
		val['9']=4;
		val['X']=5;
		val['J']=6;
		val['Q']=7;
		val['K']=8;
		val['A']=9;
		val['3']=10;
		val['2']=11;
		val['5']=12;
		val['F']=13;
		val['G']=14;
		val['7']=15;
	}
	scanf("%d",&n);
	scanf("%s",sss);
	
	while(true){
		cerr<<"\n\n A New Round :\n";
		totcard=0;
		for(int re i=0;i<n;++i)player[(i+lastwinner)%n].init();
		Debug();
		if(gameend())break;
		pii lastcard=player[lastwinner].gofirst();
		
		debug(lastwinner,lastcard);
		
		totcard+=cntcard(lastcard);
		if(lastcard.second==0){
			for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
				pii nowcard=player[i].peng(lastcard);
				if(nowcard.first==0)continue;
				lastcard=nowcard;
				totcard+=cntcard(nowcard);
				lastwinner=i;
				
				cerr<<"碰 ",debug(lastwinner,lastcard);
				lastcard.second=2;
				break;
			}
		}
		for(int re i=(lastwinner+1)%n;i!=lastwinner;i=(i+1)%n){
			pii nowcard=player[i].compete(lastcard);
			if(nowcard.first==0)continue;
			lastwinner=i;
			totcard+=cntcard(nowcard);
			lastcard=nowcard;
			
			debug(lastwinner,lastcard);
			
			if(lastcard.second==0){
				for(int re j=(lastwinner+1)%n;j!=lastwinner;j=(j+1)%n){
					pii nowcard=player[j].peng(lastcard);
					if(nowcard.first==0)continue;
					lastcard=nowcard;
					totcard+=cntcard(nowcard);
					i=lastwinner=j;
					
					cerr<<"碰 ",debug(lastwinner,lastcard);
					lastcard.second=2;
					break;
				}
			}
			
		}
		cerr<<"player "<<lastwinner<<" get "<<totcard<<" scores\n";
		score[lastwinner]+=totcard;
	//	Debug();
	}
	
	for(int re i=0;i<n;++i){
		score[i]+=player[i].now;
	}
	
	for(int re i=0;i<n;++i){
		printf("%d\n",score[i]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/83513962
今日推荐