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

题目传送门

题意分析

爆搜即可。

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

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

AC 代码

//#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;
}
posted @ 2025-07-21 22:10  TH911  阅读(17)  评论(0)    收藏  举报