Evanyou Blog 彩带

洛谷P2668 斗地主

传送门

注意模拟的先后顺序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#define re register
using namespace std ;

inline int read () {
	int f = 1 , x = 0 ;
	char ch = getchar () ;
	while(ch < '0' || ch > '9')  {if(ch == '-')  f = -1 ; ch = getchar () ;}
	while(ch >= '0' && ch <= '9')  {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ;}
	return x * f ;
}

int card[16] ;
int n , m , ans ;

bool check() {
	for(re int i = 1 ; i <= 14 ; ++ i) 
		if(card[i])  return false ;
	return true ;
}

inline void dfs(int h) {
	if(h > ans) {return ;}
	if(check()) { ans = min(ans , h) ; }
	int s1 = 0 , s2 = 0 , s3 = 0 , s4 = 0 ;
	//s1:统计单牌 , s2:统计对子 
	for(re int i = 1 ; i <= 14 ; ++ i) {
		if(card[i] == 1)  s1 ++ ;
		if(card[i] == 2)  s2 ++ ;
	}
	//s4:统计四个的牌 
	//四带二的代码 
	for(re int i = 1 ; i <= 13 ; ++ i) {
		if(card[i] == 4) {
			s4 ++ ;
			if(s1 >= 2)  s1 -= 2 ; //四带二(带两个单牌) 
			else if(s2 >= 2)  s2 -= 2 ; //四带二(带两个对子) 
			else if(s2 >= 1)  s2 -- ; //四带二(带一个对子也就是两个相同的单牌) 
		}
	}
	//s3:统计三个的牌 
	for(re int i = 1 ; i <= 13 ; ++ i) {
		if(card[i] == 3) {
			s3 ++ ;
			if(s1 >= 1)  s1 -= 1 ; //三带一 
			else if(s2 >= 1)  s2 -= 1 ; //三带一对 
		}
	}
	//ans:没有顺子情况下最小的排量 
	ans = min(ans , h + s1 + s2 + s3 + s4) ;
	//是否有顺子 
	for(re int i = 1 ; i <= 8 ; ++ i) {
		int j ;
		for(j = i ; j <= 12 ; ++ j) {
			card[j] -- ;
			if(card[j] < 0)  break ;
			if(j - i + 1 >= 5)  
				dfs(h + 1) ;
		}
		if(j == 13)  j -- ;
		while(j >= i)  card[j--]++ ;
	}
	for(re int i = 1 ; i <= 10 ; ++ i) {
		int j ;
		for(j = i ; j <= 12 ; ++ j) {
			card[j] -= 2 ;
			if(card[j] < 0)  break ;
			if(j - i + 1 >= 3)  
				dfs(h + 1) ;
		}
		if(j == 13)  j -- ;
		while(j >= i)  card[j--] += 2 ;
	}
	for(re int i = 1 ; i <= 11 ; ++ i) {
		int j ;
		for(j = i ; j <= 12 ; ++ j) {
			card[j] -= 3 ;
			if(card[j] < 0)  break ;
			if(j - i + 1 >= 2)
				dfs(h + 1) ;
		}
		if(j == 13)  j -- ;
		while(j >= i)  card[j--] += 3 ;
	}
}

int main () {
	n = read () ; m = read () ;
	while(n > 0) {
		memset(card , 0 , sizeof(card)) ;
		for(re int i = 1 ; i <= m ; ++ i) {
			int x , y ;
			x = read () ; y = read () ;
			if(x == 1 || x == 2) {
				card[11 + x] ++ ;
				continue; 
			}
			if(x == 0) {
				card[14] ++ ;
				continue ;
			}
			card[x - 2] ++ ;
		}
		ans = 24 ;
		dfs(0) ;
		printf("%d" , ans) ;
		if(n != 1)  cout << endl ;
		n-- ;
	}
	return 0 ;
}
posted @ 2019-03-28 22:25  Stephen_F  阅读(176)  评论(0编辑  收藏  举报