代码即思路,即题解

16级赵子潇  •  4年前


#include<bits/stdc++.h>
using namespace std;
const int N = 30;
const int inf = 0x3f3f3f3f;
int T, n, a[N], ans;//a[i]表示数码为i的牌有多少张 
void dfs(int sum, int step){//还有多少张牌,出了多少次 
	if(sum == 0){
		ans = min(ans, step);
		return ;
	}
	if(step >= ans)return ;
	//三顺子 
	for(int i = 3;i <= 13;i++){//起点 
		if(a[i] < 3)continue;
		for(int len = 2;i + len - 1 <= 14;len++){
			if(a[i + len - 1] >= 3){
				for(int j = i;j <= i + len - 1;j++)a[j] -= 3;
				dfs(sum - len * 3, step + 1);
				for(int j = i;j <= i + len - 1;j++)a[j] += 3;
			}else break; 
		}
	}
	//双顺子
	for(int i = 3;i <= 12;i++){//起点 
		if(a[i] < 2 || a[i + 1] < 2)continue;
		for(int len = 3;i + len - 1 <= 14;len++){
			if(a[i + len - 1] >= 2){
				for(int j = i;j <= i + len - 1;j++)a[j] -= 2;
				dfs(sum - len * 2, step + 1);
				for(int j = i;j <= i + len - 1;j++)a[j] += 2;
			}else break; 
		}
	} 
	//单顺子
	for(int i = 3;i <= 10;i++){//起点 
		if(a[i] < 1 || a[i + 1] < 1 || a[i + 2] < 1 || a[i + 3] < 1)continue;
		for(int len = 5;i + len - 1 <= 14;len++){
			if(a[i + len - 1] >= 1){
				for(int j = i;j <= i + len - 1;j++)a[j] -= 1;
				dfs(sum - len * 1, step + 1);
				for(int j = i;j <= i + len - 1;j++)a[j] += 1;
			}else break; 
		}
	}
	//四
	for(int i = 3;i <= 15;i++){
		if(a[i] < 4)continue;
		//两张单牌
		for(int j = 3;j <= 17;j++){
			if(j == i || a[j] < 1)continue;
			for(int k = 3;k <= 17;k++){
				if(k == i || a[k] < 1 || (k == j && a[j] == 1))continue;
				a[i] -= 4;
				a[j] -= 1;
				a[k] -= 1;
				dfs(sum - 6, step + 1);
				a[i] += 4;
				a[j] += 1;
				a[k] += 1;
			}
		} 
		//两张对牌
		for(int j = 3;j <= 15;j++){
			if(j == i || a[j] < 2)continue;
			for(int k = 3;k <= 15;k++){
				if(k == i || a[k] < 2 || (k == j && a[j] < 4))continue;
				a[i] -= 4;
				a[j] -= 2;
				a[k] -= 2;
				dfs(sum - 8, step + 1);
				a[i] += 4;
				a[j] += 2;
				a[k] += 2;
			}
		} 
	}
	//三
	for(int i = 3;i <= 15;i++){
		if(a[i] < 3)continue;
		//带二 
		for(int j = 3;j <= 15;j++){
			if(i == j || a[j] < 2)continue;
			a[i] -= 3;
			a[j] -= 2;
			dfs(sum - 5, step + 1);
			a[i] += 3;
			a[j] += 2;
		}
		//带一、炸弹 
		for(int j = 3;j <= 17;j++){
			if(a[j] < 1 || (i == j && a[i] < 4))continue;
			a[i] -= 3;
			a[j] -= 1;
			dfs(sum - 4, step + 1);
			a[i] += 3;
			a[j] += 1;
		}
		//不带
		a[i] -= 3;
		dfs(sum - 3, step + 1);
		a[i] += 3; 
	} 
	//先对子、火箭,最后单牌 
	for(int i = 3;i <= 15;i++){
		if(a[i] < 2)continue;
		++step;
		sum -= 2;
	} 
	if(a[16] && a[17]){
		++step;
		sum -= 2;
	}
	ans = min(ans, step + sum); 
}
int main()
{
	freopen("data.in", "r", stdin);
	scanf("%d%d", &T, &n);
	while(T--){
		memset(a, 0, sizeof(a));
		for(int i = 1;i <= n;i++){
			int A, B;
			scanf("%d%d", &A, &B);
			if(A == 0)A = 15 + B;
			else if(A == 1 || A == 2)A += 13;
			++a[A]; 
		}
		ans = inf;
		dfs(n, 0);
		printf("%d\n", ans);
	}
	return 0;
}

评论: