这是我职业生涯的最后一题了。acm留给我的太多太多... 别了。
基本的就是用枚举+贪心。
但是有几个小问题:
1.七小对是七个不同的对子。
2.东西南北.. 等不能作为顺子。
考虑这两点,基本上就没有trick了。
#include<iostream>
using namespace std;
int cnt[35];
int maso[14]={0,8,9,17,18,26,27,28,29,30,31,32,33};
int f( char c )
{
if( c>='1' && c<='9' ) return c-'1';
if( c=='m' ) return 0;
if( c=='s' ) return 9;
if( c=='p' ) return 18;
return 27;
}
char mspc( int x )
{
if( x==0 ) return 'm';
if( x==1 ) return 's';
if( x==2 ) return 'p';
return 'c';
}
bool judge4x3()
{
int i,j,ret=0;
int tem[34];
for( i=0;i<34;i++ ) tem[i]=cnt[i];
for( i=0;i<=18;i+=9 )
for( j=0;j<9;j++ )
{
if( tem[i+j]>=3 )
tem[i+j]-=3,ret++;
while( j+2<9 && tem[i+j]&& tem[i+j+1]&& tem[i+j+2] )
tem[i+j]--,tem[i+j+1]--,tem[i+j+2]--,ret++;
}
i=27;
for( j=0;j<7;j++ )
{
if( tem[i+j]>=3 )
tem[i+j]-=3,ret++;
}
return ret==4?true:false;
}
bool judge1()
{
for( int i=0;i<34;i++ )
{
if( cnt[i]>=2 )
{
cnt[i]-=2;
if( judge4x3() )
{
cnt[i]+=2;
return true;
}
cnt[i]+=2;
}
}
return false;
}
bool judge2()//judge Chii Toitsu
{
for( int i=0;i<34;i++ )
if( cnt[i]!=2 && cnt[i]!=0 )
return false;
return true;
}
bool judge3()
{
for( int i=0;i<7;i++ )
if( cnt[i+27]==0 )
return false;
for( int i=0;i<=18;i+=9 )
{
if( cnt[i]==0 || cnt[i+8]==0 )
return false;
for( int j=1;j<8;j++ )
if( cnt[i+j] )
return false;
}
return true;
}
bool judge()
{
if( judge1() ) return true;
if( judge2() ) return true;
if( judge3() ) return true;
return false;
}
int main()
{
//freopen( "A.in","r",stdin );
//freopen( "A.out","w",stdout );
int T;
scanf( "%d",&T );
while( T-- )
{
char com[11];
int rec[34],tot=0;
memset( cnt,0,sizeof(cnt) );
for( int i=0;i<13;i++ )
{
scanf("%s",com);
cnt[f(com[0])+f(com[1])]++;
}
for( int i=0;i<34;i++ )
{
cnt[i]++;
if( cnt[i]<=4 && judge() )
rec[tot++]=i;
cnt[i]--;
}
if( tot==0 )
printf( "Nooten" );
else
{
printf( "%d",tot );
for( int i=0;i<tot;i++ )
printf( " %d%c",rec[i]%9+1,mspc(rec[i]/9) );
}
printf( "\n" );
}
return 0;
}