#30. 斗地主(T1-9)

Posted zzz-hhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#30. 斗地主(T1-9)相关的知识,希望对你有一定的参考价值。

蒟蒻又双叒叕来刷模拟了

题目描述

我们将每一张牌用两个整数表示。

第一个整数表示花色:0=?,1=?,2=?,3=?

第二个整数表示数字:A10=110,J, Q, K = 11, 12, 13

数字从小到大排列为:34567890JQKA2

两张牌是相同的,当且仅当他们花色和数字都相同。

出于简化,我们只考虑以下 4 种牌型,其余情况不构成合法牌型:

(1) 单张:顾名思义,单张就是一张牌。双方牌型都是单牌时,单张 X 大过单张

Y 当且仅当 X 的数字严格大过 Y 的数字。

(2) 三带一:顾名思义,三带一就是三张数字相同的牌带一张数字不同的牌。三带

一 XXXU 大过三带一 YYYV 当且仅当 X 的数字大过 Y 的数字。

(3) 炸弹:顾名思义,炸弹就是四张数字相同的牌。任意炸弹大过上面两种牌型。

炸弹 XXXX 大过炸弹 YYYY 当且仅当 X 的数字大过 Y 的数字。

其余情况不能比大小。 出于简化,我们只考虑以下 3 种出千:

(1) 每一轮出牌中,如果双方的牌中,存在完全相同的两张牌(无论是否为同一人

持有),则存在出千。

(2) 每一轮出牌中,如果一方的出牌不能构成合法牌型,则存在出千。

(3) 每一轮出牌中,如果双方牌型没有一方能大过另一方,则存在出千。

solution

我们先判断有没有重拍,然后比较大小
没有什么很巧的办法只能使劲敲代码..

code

/*
	Auther:_Destiny
	time:2020.5.2
*/
#include <bits/stdc++.h>
#include <map>
#define ll long long
#define N 100010
#define M 1010

using namespace std;
int T, z1, z2;
int k1, k2, hua, shu, flag;
int f1[60], f2[60];
map<pair<int, int>, bool> ma;
map<int, bool> zz1, zz2;
struct node {
	int da, shu;
};

int read() {
	int s = 0, f = 0; char ch = getchar();
	while (!isdigit(ch)) f |= (ch == ‘-‘), ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

void init() {//初始化数组
	ma.clear(), zz1.clear(), zz2.clear(); z1 = 0, z2 = 0;
	memset(f1, 0, sizeof f1);
	memset(f2, 0, sizeof f2);
}

void in() {//读入的时候判断
	k1 = read();
	flag = 0;
	for (int i = 1; i <= k1; i++) {
		hua = read(), shu = read();
		if (ma[make_pair(hua, shu)] == 1) flag = 1;//判断有没有重牌
		else {
			ma[make_pair(hua, shu)] = 1;
			if (shu == 1 || shu == 2) shu += 13;
			f1[i] = shu;
			if (!zz1[shu]) zz1[shu] = 1, z1++;//记录一下牌的种数后边有用
		}
	}
	k2 = read();
	for (int i = 1; i <= k2; i++) {
		hua = read(), shu = read();
		if (ma[make_pair(hua, shu)]) flag = 1;
		else {
			ma[make_pair(hua, shu)] = 1;
			if (shu == 1 || shu == 2) shu += 13;
			f2[i] = shu;
			if (!zz2[shu]) zz2[shu] = 1, z2++;
		}
	}
	if ((k1 != 1 && k1 != 4) || (k2 != 1 && k2 != 4)) flag = 1;
	//因为只有单只,三代一和炸弹,所以如果不是1和4那就直接错
}

int work() {
	node x1, y1, xx, yy;
	if (k1 == 1 && k2 == 1) {//判断单只的大小
		x1.da = f1[1];
		xx.da = f2[1];
		if (x1.da < xx.da) return 2;
		else if (x1.da > xx.da) return 1;
		else return 0;
	}
	if (k1 == 1 && k2 == 4) {//判断王炸
		if (z2 == 1) return 2;
		else return 0;
	}
	if (k1 == 4 && k2 == 1) {
		if (z1 == 1) return 1;//判断王炸
		else return 0;
	}
	if (k1 == 4 && k2 == 4) {
		if (z1 != 1 && z1 != 2) return 0;
		if (z2 != 1 && z2 != 2) return 0;
		bool b[32] = {0};
		x1.da = f1[1], x1.shu = 1, b[f1[1]] = 1;
		for (int i = 2; i <= k1; i++)
			if (!b[f1[i]]) {
				y1.da = f1[i];
				y1.shu = 1;
			} else {
				if (f1[i] == x1.da) x1.shu++;
				if (f1[i] == y1.da) y1.shu++;
			}
		if (x1.shu == 2 || y1.shu == 2) return 0;
		memset(b, 0, sizeof b);
		xx.da = f2[1], xx.shu = 1, b[f2[1]] = 1;
		for (int i = 2; i <= k2; i++)
			if (!b[f2[i]]) {
				yy.da = f2[i];
				yy.shu = 1;
			} else {
				if (f2[i] == xx.da) xx.shu++;
				if (f2[i] == yy.da) yy.shu++;
			}
		if (xx.shu == 2 || yy.shu == 2) return 0;
		int d1, d2;
		if ((xx.shu == 4 || yy.shu == 4) && x1.shu != 4 && y1.shu != 4) return 2;
		if ((x1.shu == 4 || y1.shu == 4) && xx.shu != 4 && yy.shu != 4) return 1;
		if ((x1.shu == 4 || y1.shu == 4) && (xx.shu == 4 || yy.shu == 4)) {
			if (x1.shu == 4) d1 = x1.da;
			if (y1.shu == 4) d1 = y1.da;//如果是两只炸弹,判断炸弹的大小
			if (xx.shu == 4) d2 = xx.da;
			if (yy.shu == 4) d2 = yy.da;
			if (d1 > d2) return 1;
			else return 2;
		}
		if (x1.shu == 3) d1 = x1.da;//判断三代一大小
		if (y1.shu == 3) d1 = y1.da;
		if (xx.shu == 3) d2 = xx.da;
		if (yy.shu == 3) d2 = yy.da;
		if (d1 > d2) return 1;
		else return 2;
	}
}

int main() {
	T = read();
	while (T--) {
		init();
		in();
		if (flag == 1) {
			puts("0");
			continue;
		}
		int x = work();
		cout << x << "
";
	}
}

垃圾题


以上是关于#30. 斗地主(T1-9)的主要内容,如果未能解决你的问题,请参考以下文章

斗地主特殊牌型定义

noip2015斗地主

4.30-5.1cf补题

30秒就能看懂的JavaScript 代码片段

精心收集的 48 个 JavaScript 代码片段,仅需 30 秒就可理解

BZOJ 4325: NOIP2015 斗地主