题解:[NOIP 2015 提高组] 斗地主

洛谷P2668

Posted by TH911 on May 18, 2025

题目传送门

题意分析

爆搜即可。

优先出顺子、带牌,剩下的散排无论几张,一类牌都可以一次出完。

一个坑点:一定不要使用 else if,我因为这个导致某些操作不会被判断。

AC 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#include<random>
using namespace std;
constexpr const int N=23,V=15;
constexpr const int length[4]={0,5,3,2};
mt19937 Rand(time(0));
int cnt[V+1];
int translate(int a,int b){
	if(3<=a&&a<=13){
		return a-2;
	}else if(a==1){
		return 12;
	}else if(a==2){
		return 13;
	}else{
		if(b==1){
			return 14;
		}else{
			return 15;
		}
	}
}
bool check(){
	for(int i=1;i<=V;i++){
		if(cnt[i]){
			return false;
		}
	}
	return true;
}
int ans=2147483647;
void dfs(int step){
	if(step>=ans){
		return;
	}
	if(check()){
		ans=step;
		return;
	}
	for(int i=1;i<=3;i++){
		int pl=0;
		for(int j=1;j<=12;j++){
			if(cnt[j]>=i){
				pl++;
				//顺子[j-pl+1,j]
				if(pl>=length[i]){
					for(int k=j-pl+1;k<=j;k++){
						cnt[k]-=i;
					}
					dfs(step+1);
					for(int k=j-pl+1;k<=j;k++){
						cnt[k]+=i;
					}
				}
			}else{
				pl=0;
			}
		}
	}
	//三带二/一 
	for(int i=1;i<=V;i++){
		if(cnt[i]>=3){
			cnt[i]-=3;
			for(int j=1;j<=V;j++){
				if(cnt[j]){
					cnt[j]--;
					dfs(step+1);
					cnt[j]++;
				}
				if(cnt[j]>=2){
					cnt[j]-=2;
					dfs(step+1);
					cnt[j]+=2;
				}
			}
			cnt[i]+=3;
		}
	}
	//四带二/四 
	for(int i=1;i<=V;i++){
		if(cnt[i]>=4){
			cnt[i]-=4;
			for(int j=1;j<=V;j++){
				if(cnt[j]>=2){
                    cnt[j]-=2;
					for(int k=1;k<=V;k++){
						if(cnt[k]>=2){
							cnt[k]-=2;
							dfs(step+1);
							cnt[k]+=2;
						}
					}
                    cnt[j]+=2;
				}
				if(cnt[j]){
                    cnt[j]--;
					for(int k=1;k<=V;k++){
						if(cnt[k]){
							cnt[k]--;
							dfs(step+1);
							cnt[k]++;
						}
					}
                    cnt[j]++;
				}
			}
            cnt[i]+=4;
		}
	}
	for(int i=1;i<=V;i++){
		if(cnt[i]){
			step++;
		}
	}
	//火箭 
	if(cnt[14]&&cnt[15]){
		step--;
	}
	ans=min(ans,step);
}
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	int T,n;
	cin>>T>>n;
	while(T--){
		memset(cnt,0,sizeof(cnt));
		 
		for(int i=1;i<=n;i++){
			int a,b;
			cin>>a>>b;
			cnt[translate(a,b)]++;
		}
		ans=2147483647;
		dfs(0);
		cout<<ans<<'\n'; 
	}
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}