1. 程式人生 > >[JSOI2007]麻將 模擬 BZOJ1028

[JSOI2007]麻將 模擬 BZOJ1028

sstream time type 同時 sample etc pragma const bsp

題目描述

麻將是中國傳統的娛樂工具之一。麻將牌的牌可以分為字牌(共有東、南、西、北、中、發、白七種)和序數牌(分為條子、餅子、萬子三種花色,每種花色各有一到九的九種牌),每種牌各四張。

在麻將中,通常情況下一組和了的牌(即完成的牌)由十四張牌組成。十四張牌中的兩張組成對子(即完全相同的兩張牌),剩余的十二張組成三張一組的四組,每一組須為順子(即同花色且序數相連的序數牌,例如條子的三、四、五)或者是刻子(即完全相同的三張牌)。一組聽牌的牌是指一組十三張牌,且再加上某一張牌就可以組成和牌。那一張加上的牌可以稱為等待牌。

在這裏,我們考慮一種特殊的麻將。在這種特殊的麻將裏,沒有字牌,花色也只有一種。但是,序數不被限制在一到九的範圍內,而是在1到n的範圍內。同時,也沒有每一種牌四張的限制。一組和了的牌由3m + 2張牌組成,其中兩張組成對子,其余3m張組成三張一組的m組,每組須為順子或刻子。現給出一組3m + 1張的牌,要求判斷該組牌是否為聽牌(即還差一張就可以和牌)。如果是的話,輸出所有可能的等待牌。

輸入輸出格式

輸入格式:

包含兩行。第一行包含兩個由空格隔開整數n, m (9<=n<=400, 4<=m<=1000)。第二行包含3m + 1個由空格隔開整數,每個數均在範圍1到n之內。這些數代表要求判斷聽牌的牌的序數。

輸出格式:

輸出為一行。如果該組牌為聽牌,則輸出所有的可能的等待牌的序數,數字之間用一個空格隔開。所有的序數必須按從小到大的順序輸出。如果該組牌不是聽牌,則輸出"NO"。

輸入輸出樣例

輸入樣例#1: 復制
9 4
1 1 2 2 3 3 5 5 5 7 8 8 8
輸出樣例#1: 復制
6 7 9
枚舉;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 200005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-5
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;

inline int rd() {
	int x = 0;
	char c = getchar();
	bool f = false;
	while (!isdigit(c)) {
		if (c == ‘-‘) f = true;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return f ? -x : x;
}


ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; }



/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
	if (!b) {
		x = 1; y = 0; return a;
	}
	ans = exgcd(b, a%b, x, y);
	ll t = x; x = y; y = t - a / b * y;
	return ans;
}
*/

int n, m;
int but[maxn];
bool fg;
int tmp[maxn];
bool OK() {
	for (int i = 1; i <= n; i++) {
		if (but[i] >= 2) {// 對子
			but[i] -= 2;
			bool ok = 1;
			for (int j = 1; j <= n + 2; j++)tmp[j] = but[j];
			for (int j = 1; j <= n + 2; j++) {
				if (tmp[j] < 0) {
					ok = 0; break;
				}
				tmp[j] %= 3;
				tmp[j + 1] -= tmp[j];
				tmp[j + 2] -= tmp[j];
			}
			but[i] += 2;
			if (ok)return true;
		}
	}
	return false;
}

int main()
{
	//ios::sync_with_stdio(0);
	n = rd(); m = rd();
	for (int i = 1; i <= 3 * m + 1; i++) {
		int x; x = rd(); but[x]++;
	}
	for (int i = 1; i <= n; i++) {
		but[i]++;
		if (OK()) {
			fg = 1; cout << i << ‘ ‘;
		}
		but[i]--;
	}
	if (fg == 0)cout << "NO" << endl;
	return 0;
}




[JSOI2007]麻將 模擬 BZOJ1028