poj2044

来源:互联网 发布:打电话说中文域名到期 编辑:程序博客网 时间:2024/05/16 04:40

纠结了半天,巨难看的代码。用的广搜,状态只需记录四个角云的位置即可,这样状态数便十分可观了。

AC代码:

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
int flag[370][10],_map[17][10],squ[10][17],mat[370][17],vis[10][7][7][7][7],N,d_now;
int move[9][2]={0,0,-1,0,-2,0,1,0,2,0,0,-1,0,-2,0,1,0,2};
int S[9]={1,2,3,5,6,7,9,10,11};
int tr[4]={1,3,7,9};
struct Node
{
 int u,d,dry[4];
 void init()
 {
  memset(dry,0,sizeof(dry));
 }
};
queue<Node> Q;
void map_init()
{
 for(int i=0;i<9;i++)
 {
  int s=S[i];
  squ[i][s]=1;squ[i][s+1]=1;
  squ[i][s+4]=1;squ[i][s+5]=1;
 }
 for(int i=1;i<=16;i++)
 {
  for(int j=0;j<9;j++)
   if(squ[j][i]) _map[i][j+1]=1;
 }

}
void init()
{
 memset(flag,0,sizeof(flag));
 memset(vis,0,sizeof(vis));
 for(int i=1;i<=N;i++)
  for(int j=1;j<=16;j++)
   if(mat[i][j])
    for(int k=1;k<=9;k++)
     if(_map[j][k]) flag[i][k]=1;
}
int ok(int x,int y,int d)
{
 if(!(x>=0&&x<3&&y>=0&&y<3)) return 0;
 int u=3*x+y+1;
 if(flag[d][u]) return 0;
 return u;
}

void _set(Node &nt,int u)
{
 for(int i=0;i<4;i++)
 {
  if(tr[i]==u) nt.dry[i]=0;
  else nt.dry[i]++;
 }
}
int get_max(Node nt,int u)
{
 int m=0;
 for(int i=0;i<4;i++)
  if(tr[i]!=u) m=max(nt.dry[i],m);
 return m;
}
int tran(int u,int i,int d)
{
 int x=u/3,y=u%3;
 int v=ok(x+move[i][0],y+move[i][1],d);
 return v;
}
int bfs()
{
 if(flag[1][5]) return 0;

 Node nt,nt1;  nt.init();
 nt.u=5;nt.d=1;_set(nt,5); Q.push(nt);
 d_now=1;
 while(!Q.empty())
 {
  nt=Q.front(); Q.pop();
  if(nt.d==N)
  {
   while(!Q.empty()) Q.pop();
   return 1;
  }
  if(nt.d>d_now)
  {
   memset(vis,0,sizeof(vis));
   d_now=nt.d;
  }
  for(int i=0;i<9;i++)
  {
   int d=nt.d+1,u=tran(nt.u-1,i,d);
   if(u && get_max(nt,u)+1<7)
   {
    nt1=nt; _set(nt1,u);
    int &vi=vis[u][nt1.dry[0]][nt1.dry[1]][nt1.dry[2]][nt1.dry[3]];
    if(!vi)
    {
     nt1.u=u;nt1.d=d;
     vi=1; Q.push(nt1);
    }
   }
  }
 }
 return 0;
}
int main()
{
// freopen("test.txt","r",stdin);
 map_init();
 while(scanf("%d",&N)&&N)
 {
  for(int i=1;i<=N;i++)
   for(int j=1;j<=16;j++)
    scanf("%d",&mat[i][j]);
  init();

  printf("%d\n",bfs());
 }
 return 0;
}

 

原创粉丝点击