UVA_11210
一开始觉得这个题目比较麻烦便有点胆怯,后来鼓起勇气开始编之后,发现其实只要把每种情况考虑周全并且回溯得当的话还是不难的。
深搜中间之所以把eye设成全局变量并且放在return语句后面进行回溯,是因为我们大体可以把牌分4类,4类中最多只有一个eye,并且如果当前某一类在占用一个eye之后使这一类成为了符合要求的牌,那么这一类不占一个eye的话就一定是不符合要求的(这类牌的张数决定的)。
我的程序里面的prepare()函数是可以不用的,当时为了刷排名才刻意加了一个这样的函数。
另外,不知道外国人看到刘汝佳的下面这句话时,不知道会不会求助于Google呢……
To who knows more about Mahjong: don’t consider special winning hands such as ‘七对子’.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int p[3][15],f[10],eye;
char ap[]={'T','S','W'},b[10];
char af[][10]={"DONG","NAN","XI","BEI","ZHONG","FA","BAI"};
int dfs_f(int cur,int e)
{
int i,ok;
for(i=cur;f[i]==0&&i<7;i++);
if(i==7)
return 1;
if(f[i]==4)
return 0;
if(f[i]==3)
{
f[i]-=3;
ok=dfs_f(i,e);
f[i]+=3;
if(ok)
return 1;
}
else if(f[i]==2)
{
if(e)
return 0;
else
{
f[i]-=2;
eye=1;
ok=dfs_f(i,eye);
f[i]+=2;
if(ok)
return 1;
eye=0;
}
}
return 0;
}
int dfs_p(int s,int cur,int e)
{
int i,j,ok;
for(i=cur;p[s][i]==0&&i<9;i++);
if(i==9)
return 1;
if(p[s][i]>=3)
{
p[s][i]-=3;
ok=dfs_p(s,i,e);
p[s][i]+=3;
if(ok)
return 1;
}
if(p[s][i]>=2&&!e)
{
p[s][i]-=2;
eye=1;
ok=dfs_p(s,i,eye);
p[s][i]+=2;
if(ok)
return 1;
eye=0;
}
if(i<7&&p[s][i+1]&&p[s][i+2])
{
p[s][i]-=1;
p[s][i+1]-=1;
p[s][i+2]-=1;
ok=dfs_p(s,i,e);
p[s][i]+=1;
p[s][i+1]+=1;
p[s][i+2]+=1;
if(ok)
return 1;
}
return 0;
}
int judge()
{
int i,eye=0;
if(!dfs_f(0,eye))
return 0;
for(i=0;i<3;i++)
if(!dfs_p(i,0,eye))
return 0;
return 1;
}
int init()
{
int i,j,k;
for(i=0;i<13;i++)
{
scanf("%s",b);
if(b[0]=='0')
return 0;
if(isdigit(b[0]))
{
k=b[0]-'1';
for(j=0;;j++)
if(ap[j]==b[1])
break;
p[j][k]++;
}
else
{
for(j=0;;j++)
if(strcmp(af[j],b)==0)
break;
f[j]++;
}
}
return 1;
}
int prepare()
{
int i,j;
for(i=0;i<7;i++)
if(f[i]==4||f[i]==1)
return 0;
for(i=0;i<3;i++)
for(j=0;j<9;j++)
if(p[i][j]==1)
{
if(j==0)
{
if(!p[i][j+1])
return 0;
}
else if(j==8)
{
if(!p[i][j-1])
return 0;
}
else
{
if(!p[i][j-1]&&!p[i][j+1])
return 0;
}
}
return 1;
}
int main()
{
int i,j,k,t,ok;
t=0;
while(1)
{
memset(p,0,sizeof(p));
memset(f,0,sizeof(f));
if(!init())
break;
printf("Case %d:",++t);
ok=0;
for(i=0;i<3;i++)
for(j=0;j<9;j++)
if(p[i][j]!=4)
{
p[i][j]++;
if(prepare()&&judge())
{
ok=1;
printf(" %d%c",j+1,ap[i]);
}
p[i][j]--;
}
for(i=0;i<7;i++)
if(f[i]!=4)
{
f[i]++;
if(prepare()&&judge())
{
ok=1;
printf(" %s",af[i]);
}
f[i]--;
}
if(!ok)
printf(" Not ready\n");
else
printf("\n");
}
return 0;
}