记录编号 330018 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2015]斗地主 最终得分 100
用户昵称 Gravatar残星誓言 是否通过 通过
代码语言 C++ 运行时间 0.493 s
提交时间 2016-10-25 21:00:24 内存使用 0.20 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=20;
int n=15;
int th;int ans=2147483647;
int card[maxn];
int used[maxn];
/*
枚举顺序
	三顺子
	二顺子
	顺子
	four
	three 
	two
	one 
	ps 王不能顺子 或带出去
	wei chi dan zhang shu liang*/
int m;
bool find_one(bool flag)
{
	int tp;
	if(flag) tp=n; else tp=n-1; 
	for(int i=1;i<=tp;i++)
		if(card[i]-used[i]==1)
		{
			used[i]+=1;th=i;
			return true;
		}
		return false;
}
bool find_two(bool flag)
{	
	int tp;
	if(flag) tp=n; else tp=n-1;
	for(int i=1;i<=tp;i++)
		if(card[i]-used[i]>=2)
		{
			used[i]+=2;th=i;
			return true;
		}
		return false;
};
bool find_three()
{
	for(int i=1;i<=n;i++)
	{	
		if(card[i]-used[i]>=3)
		{
			used[i]+=3;th=i;
			return true;
		}
	
	}
	return false;
}
bool find_four()
{
	for(int i=1;i<=n;i++)
	{	
		if(card[i]-used[i]>=4)
		{
			used[i]+=4;th=i;  //printf("\nfind four=%d\n",i);
			return true;
		}
		
	}
	return false;
}
int  find_oneshunzi(int s)  //from s de shun zi chang du;
{
	int x=0;
	for(int i=s;i<n;i++)
		{
			if(card[i]-used[i]>=1)
			{
				x++;
			}
			else
			return x;
		}
	return x;
}
int  find_twoshunzi(int s)//from s de shun zi chang du;
{
	int x=0;
	for(int i=s;i<n;i++)
		{
			if(card[i]-used[i]>=2)
			{
				x++;
			}
			else
			return x;
		}
	return x;
}
int  find_threeshunzi(int s)  //from s de shun zi chang du;
{
	int x=0;
	for(int i=s;i<n;i++)
		{
			if(card[i]-used[i]>=3)
			{
				x++;
			}
			else
			return x;
		}
	return x;
}
void dfs(int X,int last)
{
		
/*	printf("\nx=%5d  last=%3d:\n",X,last);
	for(int i=1;i<=15;i++) printf("%3d ",i); putchar('\n');
	for(int i=1;i<=15;i++) printf("%3d ",card[i]-used[i]);*/
		if(X>=ans) return;
		if(last==0) {	ans=X;/*puts("233orz");*/return; }
		for(int i=3;i<=n;i++)
		{
			int x=find_oneshunzi(i); //printf("--%d--",x);
			if(x>=5)
			{	int s=i;
				for(int j=s;j<s+4;j++) used[j]++;
				for(int k=4;k<x;k++)
				{
					used[s+k]++;//puts("顺子");
					dfs(X+1,last-(k+1)); 
				}
				for(int k=i;k<i+x;k++) used[k]--;	
			}			
		}
		for(int i=3;i<=n;i++)
		{
			int x=find_twoshunzi(i);
			if(x>=3)
			{	int s=i;
				for(int j=s;j<s+2;j++) used[j]+=2;
				for(int k=2;k<x;k++)
				{
					used[s+k]+=2;//puts("二_顺子");
					dfs(X+1,last-(k+1)*2);
				}
				for(int k=i;k<i+x;k++) used[k]-=2;	
			}			
		}
		for(int i=3;i<=n;i++)
		{
			int x=find_threeshunzi(i);
			if(x>=2)
			{	int s=i;
				for(int j=s;j<s+1;j++) used[j]+=3;
				for(int k=1;k<x;k++)
				{
					used[s+k]+=3;//puts("三_顺子");
					dfs(X+1,last-(k+1)*3);
				}
				for(int k=i;k<i+x;k++) used[k]-=3;	
			}			
		}
		if(find_four())
		{
			int f=th;
			if(find_two(0))
			{
				int ff=th;
				if(find_two(0))
				{
					int fff=th;   //puts("4 dai 2 dui");
					dfs(X+1,last-8);
					used[fff]-=2;
				}
				used[ff]-=2;
			}
			if(find_one(1))
			{
				int ff=th;
				if(find_one(1))
				{
					int fff=th;	//puts("4 dai 2");
					dfs(X+1,last-6);
					used[fff]-=1;
				}
				used[ff]-=1;
			}
								//puts("炸弹");
			dfs(X+1,last-4);
			used[f]-=4;
			
		}
		if(find_three())
		{
			int f=th;
			if(find_two(0))
			{
				int ff=th;		//puts("三带一对");
				dfs(X+1,last-5);
				used[ff]-=2;
			}
			if(find_one(1))
			{
				int ff=th;		//puts("三带一");
				dfs(X+1,last-4);
				used[ff]-=1;
				
			}
			dfs(X+1,last-3);
			used[f]-=3;
		}
		if(find_two(1))
		{	int f=th;				//puts("对子");
			dfs(X+1,last-2);	
			used[f]-=2;
		}
		
		if(find_one(1))
		{	int f=th;						//puts("单张");
			dfs(X+1,last-1);
			used[f]-=1;     	//printf("|%d=%d|",th,used[th]);
		}
		
}
int main()
{	
	freopen("landlords.in","r",stdin);
	freopen("landlords.out","w",stdout);
	
	int t;
	scanf("%d%d",&t,&m);
	for(int cl=1;cl<=t;cl++)
	
	{
	memset(card,0,sizeof(card));
	memset(used,0,sizeof(used));
	ans=2147483647;
	for(int i=1;i<=m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(a==1) card[14]++;
		else
		if(a==0) card[15]++;
		else
		card[a]++;
	}
	dfs(0,m);
	printf("%d\n",ans);

	}
	return 0;
}