#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 << "\n";
	}
}

垃圾題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章