gym102460 Rush Hour Puzzle 2019ICPC Taipei

https://codeforces.com/gym/102460

目标就是让1的右端点移动到(3,6)的位置,从(3,6)出去还要两步,那么最多就是移动8步,又因为最多只有10个物品,而且我们可以用hash标记棋盘的某个状态是否出现过,那么每次尝试移动每个物品,bfs就行了,最坏情况是(10*2)^8的状态,但是由于互相碰撞的原因,实际情况会少很多状态,30ms就跑过了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod1=1e9+7;
const int mod2=998244353;
const int bas=1e9;

int ans,tot;
int ini[8][8],tmp[8][8],a[8][8];
int dir[12],len[12],inix[12],iniy[12];
struct board
{
  int a[8][8],val;
};
queue<board> q;
unordered_map<ll,bool> mp;

inline void prework()
{
  for(int i=1;i<=6;i++)
    for(int j=1;j<=6;j++)
      scanf("%d",&ini[i][j]);
  for(int i=0;i<=7;i++)
    ini[i][0]=ini[i][7]=ini[0][i]=ini[7][i]=11;
}

inline ll geths(board & x)
{
  ll t1=0,t2=0;
  for(int i=1;i<=6;i++)
    for(int j=1;j<=6;j++)
      {
	t1=(t1*11+x.a[i][j])%mod1;
	t2=(t2*11+x.a[i][j])%mod2;
      }
  return t1*bas+t2;
}

inline void mainwork()
{
  ans=-1;int x,y;
  for(int i=1;i<=6;i++)
    for(int j=1;j<=6;j++)
      {
	x=ini[i][j];tot=max(x,tot);
	if(x>0 && len[x]==0)
	  {
	    inix[x]=i;iniy[x]=j;
	    if(j+1<=6 && ini[i][j+1]==x)
	      {
		dir[x]=1;len[x]=2;
		if(j+2<=6 && ini[i][j+2]==x)
		  len[x]++;
	      }
	    else
	      {
		dir[x]=2;len[x]=2;
		if(i+2<=6 && ini[i+2][j]==x)
		  len[x]++;
	      }
	  }
      }
  if(dir[1]==1 && len[1]==2 && inix[1]==3)
    ans=0;
  if(ans<0)
    return;
  board u,d;d.val=0;ll hs;
  for(int i=0;i<=7;i++)
    for(int j=0;j<=7;j++)
      d.a[i][j]=ini[i][j];
  hs=geths(d);
  mp[hs]=true;q.push(d);
  while(!q.empty())
    {
      u=q.front();q.pop();
      for(int i=1;i<=tot;i++)
	inix[i]=0,iniy[i]=0;
      for(int i=0;i<=7;i++)
	for(int j=0;j<=7;j++)
	  {
	    d.a[i][j]=u.a[i][j];
	    x=d.a[i][j];
	    if(!inix[x])
	      inix[x]=i,iniy[x]=j;
	  }
      d.val=u.val+1;
      for(int i=1;i<=tot;i++)
	if(dir[i]==1)
	  {
	    x=inix[i];y=iniy[i];
	    if(u.a[x][y-1]==0)
	      {
		for(int j=0;j<len[i];j++)
		  d.a[x][y-1+j]=u.a[x][y+j];
		d.a[x][y+len[i]-1]=0;
		if(d.a[3][6]==1){ans=d.val+2;return;}
		hs=geths(d);
		if(!mp[hs] && d.val<=7)
		  mp[hs]=true,q.push(d);
		for(int j=y-1;j<=y+len[i]-1;j++)
		  d.a[x][j]=u.a[x][j];
	      }
	    if(u.a[x][y+len[i]]==0)
	      {
		for(int j=0;j<len[i];j++)
		  d.a[x][y+1+j]=u.a[x][y+j];
		d.a[x][y]=0;
		if(d.a[3][6]==1){ans=d.val+2;return;}
		hs=geths(d);
		if(!mp[hs] && d.val<=7)
		  mp[hs]=true,q.push(d);
		for(int j=y;j<=y+len[i];j++)
		  d.a[x][j]=u.a[x][j];
	      }
	  }
	else
	  {
	    x=inix[i];y=iniy[i];
	    if(u.a[x-1][y]==0)
	      {
		for(int j=0;j<len[i];j++)
		  d.a[x-1+j][y]=u.a[x+j][y];
		d.a[x+len[i]-1][y]=0;
		hs=geths(d);
		if(!mp[hs] && d.val<=7)
		    mp[hs]=true,q.push(d);
		for(int j=x-1;j<=x+len[i]-1;j++)
		  d.a[j][y]=u.a[j][y];
	      }
	    if(u.a[x+len[i]][y]==0)
	      {
		for(int j=0;j<len[i];j++)
		  d.a[x+1+j][y]=u.a[x+j][y];
		d.a[x][y]=0;
		hs=geths(d);
		if(!mp[hs] && d.val<=7)
		  mp[hs]=true,q.push(d);
		for(int j=x;j<=x+len[i];j++)
		  d.a[j][y]=u.a[j][y];
	      }
	    
	  }
    }
  if(ans==0 || ans>10)
    ans=-1;
}

inline void print()
{
  printf("%d\n",ans);
}

int main()
{
  prework();
  mainwork();
  print();
  return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/108504327