【NOIP2015提高组Day1】斗地主

简单,暴力模拟

#include<cstdio>
#include<cstring>
using namespace std;
int a[18],f[18][18][18][18];
int ans;
int min(int x,int y){return x<y ? x:y;}
int biao(int a,int b,int c,int d)
{
    int s=a+b+c+d;
    if (a>0) s=min(s,f[a-1][b][c][d]+1);
    if (b>0) s=min(s,f[a][b-1][c][d]+1);
    if (c>0) s=min(s,f[a][b][c-1][d]+1);
    if (d>0) s=min(s,f[a][b][c][d-1]+1);
    if (a>0 && c>1) s=min(s,f[a-1][b][c-2][d]+1);
    if (a>0 && d>1) s=min(s,f[a-1][b][c][d-2]+1);
    if (b>0 && c>0) s=min(s,f[a][b-1][c-1][d]+1);
    if (b>0 && d>0) s=min(s,f[a][b-1][c][d-1]+1);
    return s;
}
void dfs(int s)
{
	int i,j;
	int b=0,c=0,d=0,e=0;
	for (i=3;i<=16;i++)
	{
		if (a[i]==4) b++;
		else if (a[i]==3) c++;
		else if (a[i]==2) d++;
		else if (a[i]==1) e++;
	}
	ans=min(ans,f[b][c][d][e]+s);
	for (i=3;i<=16;i++)
	{
		j=0;
		while (i+j<=14&&a[i+j]>=1)//单顺子 
		{
			if (j>=4)
			{
				for (int k=i;k<=i+j;k++) a[k]--;
				dfs(s+1);
				for (int k=i;k<=i+j;k++) a[k]++;
			}
			j++;
		}
		j=0;
		while (i+j<=14&&a[i+j]>=2)//双顺子
		{
			if (j>=2)
			{
				for (int k=i;k<=i+j;k++) a[k]-=2;
				dfs(s+1);
				for (int k=i;k<=i+j;k++) a[k]+=2;
			}
			j++;
		}
		j=0;
		while (i+j<=14&&a[i+j]>=3)//三顺子
		{
			if (j>=2)
			{
				for (int k=i;k<=i+j;k++) a[k]-=3;
				dfs(s+1);
				for (int k=i;k<=i+j;k++) a[k]+=3;
			}
			j++;
		}
	}
}
int main()
{
	freopen("landlords.in","r",stdin);
	freopen("landlords.out","w",stdout);
	int t,n,i,j,k,l;
	scanf("%d%d",&t,&n);
    for (i=0;i<=17;i++)
        for (j=0;j<=17;j++)
            for (k=0;k<=17;k++)
                for (l=0;l<=17;l++)
                	f[i][j][k][l]=biao(i,j,k,l);
	while (t-->0)
	{
		memset(a,0,sizeof(a));
		for (i=1;i<=n;i++)
		{
			scanf("%d%d",&j,&k);
			if (j>2) a[j]++;
			else if (j>0) a[j+13]++;
			else a[16]++;
		}
		ans=1e9;
		dfs(0);
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Larry1118/article/details/85015788