【luogu2668斗地主】模拟

题目描述:

输入格式:

输出格式:

输入样例:

1:

1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1

2:

1 17
12 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2

输出样例:

1:

  3

2:

  4

数据范围:

思想:模拟

代码:

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#define MAXN 100000
using namespace std;
int card[17],cnt,ans=5211314,T,n;
int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void dfs(int pos)
{
	if(pos>=ans)return;////////求有多少个单顺子 
	int k=0;
	for(int i=3;i<=14;i++)
	{
		if(!card[i])k=0;
		else{
			k++;
			if(k>=5){
				for(int j=i;j>=j-k+1;j--)
				card[j]--;
				dfs(pos+1);
				for(int j=i;j>=j-k+1;j--)
				card[j]++;
			}
		}
	}
	k=0;
	for(int i=3;i<=14;i++)////求有多少个双顺子 
	{
		if(card[i]<2)k=0;
		else{
			k++;
			if(k>=3)
			{
				for(int j=i;j>=i-k+1;j--)
				card[j]-=2;
				dfs(pos+1);
				for(int j=i;j>=j-k+1;j--)
				card[j]+=2;
			}
		}
	}
	for(int i=2;i<=14;i++)////三张牌的情况 
	{
	  if(card[i]<=3)
		{
			if(card[i]<3)continue;
			card[i]-=3;
			for(int j=2;j<=15;j++)////三张牌带一张牌 
			{
				if(j==i||card[j]<1)continue;
				card[j]--;
				dfs(pos+1);
				card[j]++;
			}
			for(int j=2;j<=15;j++)
			{
				if(j==i||card[j]<2)continue;////三张牌带两张牌 
				card[j]-=2;
				dfs(pos+1);
				card[j]+=2;
			}
			card[i]+=3;
		}
	  else
		{
			card[i]-=3;
			for(int j=2;j<=15;j++)
			{
				if(j==i||card[j]<1)continue;
				card[j]--;
				dfs(pos+1);
				card[j]++; 
			}
			for(int j=2;j<=15;j++)
			{
				if(j==i||card[j]<2)continue;
				card[i]-=2;
				dfs(pos+1);
				card[j]+=2;
			}
			card[i] += 3;//三张带别的
			card[i] -= 4;//四张带两个单张
			for(int j = 2; j <= 15; ++j){
				if(j == i || card[j] < 1) continue;
				card[j]--;
				for(int k = 2; k <= 15; ++k){
					if(k == j || card[k] < 1) continue;
					card[k]--;
					dfs(pos+1);
					card[k]++;
			    }
			    card[j]++;
			}
			for(int j = 2; i <= 14; ++j){////四张带两个对 
				if(j == i || card[j] < 2) continue;
				card[j] -= 2;
				for(int k = 2; k <= 14; ++k){
					if(j == k || card[k] < 2) continue;
					card[k] -= 2;
					dfs(pos+1);
					card[k] += 2;
				}
				card[j] += 2;
			}
			card[i] += 4;
		}
	}
	for(int i=2;i<=15;++i)////考虑剩下的牌,每次都能一次出尽每种的所有牌 
	if(card[i])pos++;
	ans=min(ans,pos);
}
int main()
{
	T=read();n=read();
	while(T--)
	{
		ans=2147483647;
		memset(card,0,sizeof(card));
		int ai,bi;
		for(int i=1;i<=n;i++)
		{
			ai=read();bi=read();
			if(ai==1)card[14]++;
			else if(ai==0)card[15]++;
			else card[ai]++;
		}
		dfs(0);
		printf("%d
",ans);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/yelir/p/11425226.html