Mayan游戏

题面

总而言之,四条剪枝原则:

(1)交换两个颜色相同的块没有意义

(2)一个块的左边是非空块时不需要考虑左移,因为会和之前的块右移重复,即只有当左块为空时才左移

(3)根据题目优先度的排序,可以知道,右移优先于左移,所以在dfs时先考虑右移

(4)如果有一种颜色当前的块数目x满足1<=x<=2,则此情况不合法

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
bool vis[10][10];
bool flag[11];
int map[10][10];
int step[10][5];
int count[11];
int n,N;
int del( )
{
  memset( vis,1,sizeof vis );
  int res=0;
  int l,r,u,d,x,y,t;
  bool cs=0;
  for(int i=1;i<=5;i++)
    for(int j=1;j<=7;j++)
      if( map[ i ][ j ] )
    if( ( j>=2  && map[ i ][ j-1 ] ) || j==1 )
      {
        l=r=i;
        u=d=j;
        while( l>=2 && map[ l-1 ][ j ]==map[ i ][ j ] ) 
          l--;
        while(r<4 && map[ r+1 ][ j ]==map[ i ][ j ] ) 
          r++;
        while( d>=2 && map[ i ][ d-1 ]==map[ i ][ j ] ) 
          d--;
        while( u<=6 && map[ i ][ u+1 ]==map[ i ][ j ] ) 
          u++; 
        if( r-l>=2 )
          for(int k=l;k<=r;k++)
        vis[ k ][ j ]=0;
        if( u-d>=2 )
          for(int k=d;k<=u;k++)
        vis[ i ][ k ]=0;
      }
  for(int i=1;i<=5;i++)
    for(int j=1;j<=7;j++)
      if( !vis[ i ][ j ] )
    {
      res++;
      map[ i ][ j ]=0;
    }
  for(int i=1,j;i<=5;i++)
    {
      for(j=1;j<=7;j++)
    if( !map[ i ][ j ] )
      break;
      x=j;
      for( ;j<=7;j++ )
    if( map[ i ][ j ] )
      break;
      if( j==8 )
    continue;
      y=j-1;
      t=0;
      for( j=x;j<=7;j++ )
        {
      t++;
      if( !map[ i ][ y+t ] || map[ i ][ j ]) 
        break;
      map[ i ][ j ]=map[ i ][ y+t ];
      map[ i ][ y+t ]=0;
      cs=1;
        }
    }
  if( cs )
    res+=del( );
  return res;
}
bool judge( )
{
  memset( count,0x0,sizeof count );
  for(int i=1;i<=5;i++)
    for(int j=1;j<=7;j++)
      count[ map[ i ][ j ] ]++;
  for(int i=1;i<=N;i++)
    if( count[ i ]>=1 && count[ i ]<=2 )
      return 0;
  return 1;
}
void dfs(int num,int tot)
{
  if( !judge( ) )
    return ;
  if( num>=n+1 )
    {
      if( !tot )
    {
      cout<<"搜索次数 : "<<zzl<<endl;
      for(int i=1;i<=n;i++)
        printf("%d %d %d\n",step[ i ][ 1 ]-1,step[ i ][ 2 ]-1,step[ i ][ 3 ] );
      exit(0);
    }
      return ;
    }
  int x,y;
  int temp[10][10],p,q;
  bool cs;
  for(int i=1;i<=5;i++)
    for(int j=1;j<=7;j++)
      temp[ i ][ j ]=map[ i ][ j ];
  for(int i=1;i<=5;i++)
    for(int j=1;j<=7;j++)
      {
    if( map[ i ][ j ] )
      {
        cs=1;
        if( i<=4 &&map[ i ][ j ]!=map[ i+1 ][ j ] )
          {
        swap( map[ i ][ j ],map[ i+1 ][ j ] );
        step[ num ][ 1 ]=i;
        step[ num ][ 2 ]=j;
        step[ num ][ 3 ]=1;
        p=tot-del();
        dfs( num+1,p );
        cs=0;
          }
        if( !cs )
          {
        cs=1;
        for(p=1;p<=5;p++)
          for(q=1;q<=7;q++)
            map[ p ][ q ]=temp[ p ][ q ];
          }
        if( i>=2 && !map[ i-1 ][ j ] )
          {
        swap( map[ i ][ j ],map[ i-1 ][ j ] );
        step[ num ][ 1 ]=i;
        step[ num ][ 2 ]=j;
        step[ num ][ 3 ]=-1;
        p=tot-del();
        dfs( num+1,p );
        cs=0;
          }
        if( !cs )
          for(p=1;p<=5;p++)
        for(q=1;q<=7;q++)
          map[ p ][ q ]=temp[ p ][ q ];
      }
      }
}
int main()
{
  int x,y=0;
  scanf("%d",&n);
  for(int i=1,j;i<=5;i++)
    {
      j=0;
      scanf("%d",&x);
      while( x )
    {
      map[ i ][ ++j ]=x;
      if( !flag[ x ] )
        {
          flag[ x ]=1;
          N++;
        }
      y++;
      scanf("%d",&x);
    }
    }
  dfs( 1,y );
  cout<<-1<<endl;
  return 0;
}

  

posted @ 2019-09-15 13:40  [jackeylove]  阅读(171)  评论(0编辑  收藏  举报