【解题报告】洛谷P2668 斗地主

【解题报告】洛谷P2668 斗地主

题目链接

https://www.luogu.com.cn/problem/P2668

思路

大模拟+搜索

按照从顺子开始的顺序贪心,从三顺子先出,到双顺子,然后到顺子

然后出四带二,三带二,三带一,然后最后就是可以一次出完的那种了

这个题目呢贪心的思路想到不难,但是模拟出来及其考察代码能力

所以我就炸了

我代码能力超蒻的好不好

那是不是今年再出一个大模拟我就炸了

还有一个点就在于回溯

我们每次搜进去之后记得出来的时候回溯,以便搜索其他的状态,这样就比较方便了

强烈建议多练大模拟

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#define int long long
using namespace std;
int T,n,ans;
int a[20];
void dfs(int x)
{
	if(x>=ans) return ;
	int k=0;
	for(int i=3;i<=14;i++)
	{
		if(a[i]==0) k=0;
		else
		{
			k++;
			if(k>=5)
			{
				for(int j=i;j>=i-k+1;j--)
				a[j]--;
				dfs(x+1);
				for(int j=i;j>=i-k+1;j--)
				a[j]++;
			}
		}
	}
	
	k=0;
	for(int i=3;i<=14;i++)
	{
		if(a[i]<=1) k=0;
		else
		{
			k++;
			if(k>=3)
			{
				for(int j=i;j>=i-k+1;j--)
				a[j]-=2;
				dfs(x+1);
				for(int j=i;j>=i-k+1;j--)
				a[j]+=2;
			}
		}
	}
	
	k=0;
	for(int i=3;i<=14;i++)
	{
		if(a[i]<=2) k=0;
		else
		{
			k++;
			if(k>=2)
			{
				for(int j=i;j>=i-k+1;j--)
				a[j]-=3;
				dfs(x+1);
				for(int j=i;j>=i-k+1;j--)
				a[j]+=3;
			}
		}
	}
	
	for(int i=2;i<=14;i++)
	{
		if(a[i]<=3)
		{
			if(a[i]<=2) continue;
			a[i]-=3;
			for(int j=2;j<=15;j++)
			{
				if(a[j]<=0||j==i) continue;
				a[j]--;
				dfs(x+1);
				a[j]++;
			}
			for(int j=2;j<=14;j++)
			{
				if(a[j]<=1||j==i) continue;
				a[j]-=2;
				dfs(x+1);
				a[j]+=2;
			}
			a[i]+=3;
		}
		else
		{
			a[i]-=3;
			for(int j=2;j<=15;j++)
			{
				if(a[j]<=0||j==i) continue;
				a[j]--;
				dfs(x+1);
				a[j]++;
			}
			for(int j=2;j<=14;j++)
			{
				if(a[j]<=1||j==i) continue;
				a[j]-=2;
				dfs(x+1);
				a[j]+=2;
			}
			a[i]+=3;
			
			a[i]-=4;
			for(int j=2;j<=15;j++)
			{
				if(a[j]<=0||j==i) continue;
				a[j]--;
				for(int k=2;k<=15;k++)
				{
					if(a[k]<=0||k==j) continue;
					a[k]--;
					dfs(x+1);
					a[k]++;
				}
				a[j]++;
			}
			for(int j=2;j<=14;j++)
			{
				if(a[j]<=1||j==i) continue;
				a[j]-=2;
				for(int k=2;k<=14;k++)
				{
					if(a[k]<=1||k==j) continue;
					a[k]-=2;
					dfs(x+1);
					a[k]+=2; 
				}
				a[j]+=2;
			}
			a[i]+=4;
		}
	}
	
	for(int i=1;i<=15;i++)
	{
		if(a[i])
		x++;
	}
	ans=min(ans,x);
}
signed main()
{
	cin>>T>>n;
	while(T--)
	{
		ans=1e9;
		memset(a,0,sizeof(a));
		for(int i=1;i<=n;i++)
		{
			int x,y;
			cin>>x>>y;
			if(x==0) 
			a[15]++;
			else if(x==1)
			a[14]++;
			else
			a[x]++;
		}
		dfs(0);
		cout<<ans<<'\n';
	}
	return 0;
}
posted @ 2021-10-14 17:36  wweiyi  阅读(19)  评论(0编辑  收藏  举报
js脚本