HDU 4431 麻将题

这是我职业生涯的最后一题了。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;
}



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值