96pts TLE 求救
查看原帖
96pts TLE 求救
1285691
yinbe2楼主2024/2/25 17:53
#include<iostream>
#include<cstring>
using namespace std;
int T,n,sum[20],Min;
namespace INPUT_SPACE{
	const int S=(1ll<<30)+5;char B[S],*H,*T;inline int gc() { if(H==T) T=(H=B)+fread(B,1,S,stdin);return (H==T)?EOF:*H++; }
	inline unsigned int inn() { unsigned int x,ch;while((ch=gc())<'0'||ch>'9');x=ch^'0';while((ch=gc())>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; }
}using INPUT_SPACE::inn;
void dfs(int t,int cnt)
{
	if(t>=Min)return;//最优性剪枝 
	if(cnt&&t+1==Min)return;//如果还剩牌且轮数+1等于目前最优解,不管怎么出都不会比目前最优解好 
	int k=0;
	for(int i=3;i<=14;i++)//单顺子 
	{
		if(sum[i]==0)k=0;
		else
		{
			k++;
			if(k>=5)
			{
				for(int j=i;j>=i-k+1;j--)sum[j]--;
				dfs(t+1,cnt-k);
				for(int j=i;j>=i-k+1;j--)sum[j]++;
			}
		}
	}
	k=0;
	for(int i=3;i<=14;i++)//双顺子 
	{
		if(sum[i]<=1)k=0;
		else
		{
			k++;
			if(k>=3)
			{
				for(int j=i;j>=i-k+1;j--)sum[j]-=2;
				dfs(t+1,cnt-2*k);
				for(int j=i;j>=i-k+1;j--)sum[j]+=2;
			}
		}
	}
	k=0;
	for(int i=3;i<=14;i++)//三顺子 
	{
		if(sum[i]<=2)k=0;
		else
		{
			k++;
			if(k>=2)
			{
				for(int j=i;j>=i-k+1;j--)sum[j]-=3;
				dfs(t+1,cnt-3*k);
				for(int j=i;j>=i-k+1;j--)sum[j]+=3;
			}
		}
	}
	for(int i=2;i<=14;i++)//带牌 
	{
		if(sum[i]==3)//三带一 
		{
			sum[i]-=3;
			for(int j=2;j<=15;j++)//带一张 
			{
				if(sum[j]==0||i==j)continue;
				sum[j]--;
				dfs(t+1,cnt-4);
				sum[j]++;
			}
			for(int j=2;j<=14;j++)//带一对 
			{
				if(sum[j]<=1||i==j)continue;
				sum[j]-=2;
				dfs(t+1,cnt-5);
				sum[j]+=2;
			}
			sum[i]+=3;
		}
		else if(sum[i]==4)
		{
			sum[i]-=3;//三带一 
			for(int j=2;j<=15;j++)//带一张 
			{
				if(sum[j]==0||i==j)continue;
				sum[j]--;
				dfs(t+1,cnt-4);
				sum[j]++;
			}
			for(int j=2;j<=14;j++)//带一对 
			{
				if(sum[j]<=1||i==j)continue;
				sum[j]-=2;
				dfs(t+1,cnt-5);
				sum[j]+=2;
			}
			sum[i]+=3;
			sum[i]-=4;//四带二
			for(int j=2;j<=15;j++)//带二张 
			{
				if(sum[j]==0||i==j)continue;
				sum[j]--;
				for(int k=2;k<=15;k++)
				{
					if(sum[k]==0||i==k)continue;
					sum[k]--;
					dfs(t+1,cnt-6);
					sum[k]++;
				}
				sum[j]++;
			}
			for(int j=2;j<=14;j++)//带二对 
			{
				if(sum[j]<=1||i==j)continue;
				sum[j]-=2;
				for(int k=2;k<=14;k++)
				{
					if(sum[k]<=1||i==k)continue;
					sum[k]-=2;
					dfs(t+1,cnt-8);
					sum[k]+=2;
				}
				sum[j]+=2;
			}
			sum[i]+=4;
		}
	}
	for(int i=2;i<=15;i++)if(sum[i])t++;//出剩下的牌 
	Min=min(Min,t);
	return;
}
int main()
{
//	freopen("p2668.in","r",stdin);
//	freopen("p2668.out","w",stdout);
//	scanf("%d%d",&T,&n);
	T=inn();
	n=inn(); 
	while(T--)
	{
		Min=0x3f3f3f3f;
		memset(sum,0,sizeof(sum));
		for(int i=1;i<=n;i++)
		{
			int a,b;
//			scanf("%d%d",&a,&b);
			a=inn();
			b=inn();
			if(a==0)
			{
				sum[15]++;
			}
			else if(a==1)
			{
				sum[14]++;
			}
			else
			{
				sum[a]++;
			}
		}
		dfs(0,n);
		printf("%d\n",Min);
	}
	return 0;
}

评测记录

2024/2/25 17:53
加载中...