洛谷 #2668. 斗地主

版权声明:转载请注明出处 https://blog.csdn.net/qq_41593522/article/details/84403024

题意

按规则出牌,问最少几步出完

规则详见

题解

先考虑各种顺子,用顺子或不用顺子进行dfs

剩下的牌可贪心

调试记录

30分,每次memcpy的锅,不能每次memcpy,先把整个顺子找出来,然后从后面往前面减

95分,不能先贪心预处理,因为王可以扔进三带一、三带二、四带二里面去

然后2个王还不能当普通对子用

贪心还是要被卡2333

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
#define maxn 25
#define INF 0x3f3f3f3f

using namespace std;

int n, cnt[maxn], ans;

const int id[14] = {0, 13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

int c[maxn];
int calc(){
	int tmp = INF;
	int res = 0;
	if (cnt[0] == 2){
		memset(c, 0, sizeof c);
		c[1] = 2;
		for (int i = 1; i <= 13; i++) c[cnt[i]]++;
	
		while (c[4] > 0 && c[1] > 1) c[4] -= 1, c[1] -= 2, res++;
		while (c[4] > 0 && c[2] > 1) c[4] -= 1, c[2] -= 2, res++;
		while (c[4] > 1) c[4] -= 2, res++;
		while (c[4] > 0 && c[2] > 0) c[4] -= 1, c[2] -= 1, res++;
	
		while (c[3] > 0 && c[2] > 0) c[3] -= 1, c[2] -= 1, res++;
		while (c[3] > 0 && c[1] > 0) c[3] -= 1, c[1] -= 1, res++;
	
		tmp = min(tmp, res + c[1] + c[2] + c[3] + c[4]);
	
		res = 1; memset(c, 0, sizeof c);
		for (int i = 1; i <= 13; i++) c[cnt[i]]++;
	
		while (c[4] > 0 && c[1] > 1) c[4] -= 1, c[1] -= 2, res++;
		while (c[4] > 0 && c[2] > 1) c[4] -= 1, c[2] -= 2, res++;
		while (c[4] > 1) c[4] -= 2, res++;
		while (c[4] > 0 && c[2] > 0) c[4] -= 1, c[2] -= 1, res++;
	
		while (c[3] > 0 && c[2] > 0) c[3] -= 1, c[2] -= 1, res++;
		while (c[3] > 0 && c[1] > 0) c[3] -= 1, c[1] -= 1, res++;
	
		tmp = min(tmp, res + c[1] + c[2] + c[3] + c[4]);
	}
	else{
		memset(c, 0, sizeof c);
		for (int i = 0; i <= 13; i++) c[cnt[i]]++;
	
		while (c[4] > 0 && c[1] > 1) c[4] -= 1, c[1] -= 2, res++;
		while (c[4] > 0 && c[2] > 1) c[4] -= 1, c[2] -= 2, res++;
		while (c[4] > 1) c[4] -= 2, res++;
		while (c[4] > 0 && c[2] > 0) c[4] -= 1, c[2] -= 1, res++;
	
		while (c[3] > 0 && c[2] > 0) c[3] -= 1, c[2] -= 1, res++;
		while (c[3] > 0 && c[1] > 0) c[3] -= 1, c[1] -= 1, res++;
	
		tmp = min(tmp, res + c[1] + c[2] + c[3] + c[4]);
	}
	
	return tmp;
}

const int data[4] = {0, 5, 6, 6};

void dfs(int step){
	if (step >= ans) return;
	ans = min(ans, step + calc());
	
	int tot, k;
	for (int i = 2; i <= 13; i++){
		for (int j = 3; j >= 1; j--){
			if (cnt[i] >= j){
				tot = 0;
				for (k = i; k <= 13 && cnt[k] >= j; k++) cnt[k] -= j, tot += j;
				for (; --k >= i; cnt[k] += j, tot -= j)
					if (tot >= data[j]) dfs(step + 1);
			}
		}
	}
}

int main(){
	int T; scanf("%d%d", &T, &n);
	
	while (T--){
		memset(cnt, 0, sizeof cnt);
		int pre = 0;
		for (int color, x, i = 1; i <= n; i++){
			scanf("%d%d", &x, &color);
//			if (x == 0 && pre == 0) pre = 1;
//			if (x != 0) cnt[id[x]]++;
			cnt[id[x]]++;
		}
		
		ans = INF;
		dfs(0);
		printf("%d\n", pre + ans);
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41593522/article/details/84403024
今日推荐