uva 11210 Chinese Mahjong

题目:Chinese Mahjong


思路:

枚举添加的牌和两张的对子。

每次取编号最小的那张牌配对,全部可以陪玩就说明和了。


注意:

1、每种牌的数量不能超过4。

2、把所有牌型编号后,不能把类似 9 10 11 ( 九桶,一条,二条 ) 这种的看成同花顺。


代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;

#define n 13
#define m 34

map<string,int> mp;	//牌对应的序号 
string id[m+5];

vector<int> a;
int num[m+5]= {0};

bool still[m+5]= {0};

vector<int> p;

void init() {	//初始化编号 
	for(int i=1; i<=9; i++) {
		string x=" ";
		x[0]=i+'0';
		mp[x+"T"]=i;
		id[i]=x+"T";
	}
	for(int i=10; i<=18; i++) {
		string x=" ";
		x[0]=i+'0'-9;
		mp[x+"S"]=i;
		id[i]=x+"S";
	}
	for(int i=19; i<=27; i++) {
		string x=" ";
		x[0]=i+'0'-18;
		mp[x+"W"]=i;
		id[i]=x+"W";
	}
	mp["DONG"]=28,mp["NAN"]=29,mp["XI"]=30,mp["BEI"]=31;
	id[28]="DONG",id[29]="NAN",id[30]="XI",id[31]="BEI";
	mp["ZHONG"]=32,mp["FA"]=33,mp["BAI"]=34;
	id[32]="ZHONG",id[33]="FA",id[34]="BAI";
}

void print(int x) {
	printf("Case %d:",x);
	for(int i=0; i<p.size(); i++) {
		cout<<' '<<id[p[i]];
	}
	if(!p.size()) printf(" Not ready");
	printf("\n");
}

bool readin() {
	memset(num,0,sizeof(num));
	a.clear();
	
	for(int i=1; i<=n; i++) {
		string x;
		if(!(cin>>x)||x[0]=='0') return false;
		a.push_back(mp[x]);
		num[a[i-1]]++;
	}
	sort(a.begin(),a.end());
	return true;
}

bool judge(int x) {	//判断能否以此牌开始组成同花顺 
	if(1<=x&&x<=7) return true;
	if(10<=x&&x<=16) return true;
	if(19<=x&&x<=25) return true;
	return false;
}

bool dfs(vector<int> b) {	//判断是否能和 
	bool flag=0;

	for(int i=0; i<=n; i++) {
		if(still[i]) {
			flag=true;
			still[i]=false;
			if(num[b[i]]>=3) {
				still[i+1]=still[i+2]=false;
				num[b[i]]-=3;
				if(dfs(b)) {
					still[i]=true;
					num[b[i]]+=3;
					still[i+1]=still[i+2]=true;
					return true;
				}
				num[b[i]]+=3;
				still[i+1]=still[i+2]=true;
			}
			if(num[b[i]+1]&&num[b[i]+2]&&judge(b[i])) {
				int two=-1,three=-1;
				for(int j=i; j<=n; j++) {
					if(b[j]==b[i]+1&&still[j]&&!(~two)) {
						two=j;
						still[j]=false;
						num[b[j]]--;
					}
					if(b[j]==b[i]+2&&still[j]&&!(~three)) {
						three=j;
						still[j]=false;
						num[b[j]]--;
					}
				}
				num[b[i]]--;
				if(dfs(b)) {
					still[i]=true;
					still[two]=still[three]=true;
					num[b[i]]++,num[b[two]]++,num[b[three]]++;
					return true;
				}
				still[two]=still[three]=true;
				num[b[i]]++,num[b[two]]++,num[b[three]]++;
			}
			still[i]=true;
			break;
		}
	}
	if(flag) return false;
	return true;
}

void findjiang(int x,vector<int> b) {	//枚举两张一样的牌 
	sort(b.begin(),b.end());
	for(int i=1; i<=m; i++) {
		if(num[i]>=2) {
			for(int j=0; j<=n; j++) {
				still[j]=true;
			}
			num[i]-=2;
			int y=0;
			for(int j=b.size()-1; j>=0; j--) {
				if(b[j]==i) y++,still[j]=false;
				if(y>=2) break;
			}
			if(dfs(b)) {
				p.push_back(x);
				num[i]+=2;
				return;
			}
			num[i]+=2;
		}
	}
}

void add() {	//枚举添加的牌
	p.clear();
	for(int i=1; i<=m; i++) {
		if(num[i]==4) continue;
		num[i]++;
		a.push_back(i);
		findjiang(i,a);
		a.pop_back();
		num[i]--;
	}
}

int main() {

	init();

	int T=0;
	while(readin()) {
		add();
		print(++T);
	}

	return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值