BZOJ 1028: [JSOI2007]麻将

/*
* 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1028
* 顺子:三个相连的数字
* 刻子:三个相同的数字
* 对子:两个相同的数字
* 和牌:m个顺子或者刻子加上一个对子
* 现在给出3*m+1个牌,问能不能够和牌,能够和牌的牌号分别可以是。。。
*
* 分析:
* 直接贪心加枚举对子,然后再判能不能够和牌
*
* */

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int X = 3005;

int a[X],n,m;
int b[X];

bool check(){
	for(int k=1;k<=n;k++){
		if(a[k]<2)
			continue;

		bool ok = true;
		
		for(int i=1;i<=n;i++)
			b[i] = a[i];
		b[k] -= 2;
		
		for(int i=1;i<=n;i++){
			if(b[i]==0)
				continue;
			b[i] %= 3;
			if(b[i]==0)
				continue;
			if(i>n-2){
				ok = false;
				break;
			}
			if(b[i+1]<b[i]||b[i+2]<b[i]){
				ok = false;
				break;
			}
			b[i+1] -= b[i];
			b[i+2] -= b[i];
			b[i] = 0;
		}
		if(ok)
			return true;
	}
	return false;
}

int main(){
	freopen("sum.in","r",stdin);
	while(cin>>n>>m){
		int tot = 3*m+1;
		int x;
		memset(a,0,sizeof(a));
		for(int i=1;i<=tot;i++){
			scanf("%d",&x);
			a[x] ++;
		}
		bool ok = false;
		for(int i=1;i<=n;i++){
			a[i] ++;
			if(check()){
				ok?printf(" "):ok = 1;
				printf("%d",i);
			}
			a[i] --;
		}
		ok?puts(""):puts("NO");
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/yejinru/p/2838890.html