题意:给出6层的塔,假设当前位置为 (x,y),我们可以有四个方向的交换。
题解:所以我们可以通过,将所有的数存到一行,然后双重hash这个数组状态,双向bfs就可以了。
AC代码:
#include<stdio.h>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
pair<ll,ll>pp;
pair<ll,ll> Hash(ll a[21])
{
ll ans1=0,ans2=0;
for(ll i=0;i<21;i++)
ans1=(ans1*1000000013+a[i])%1000000007;
for(ll i=0;i<21;i++)
ans2=(ans2*1000000013+a[i])%1000000009;
pp.first=ans1;
pp.second=ans2;
return pp;
}
map<pair<ll,ll>,char>mp;
map<pair<ll,ll>,ll>mpp;
ll s[21],e[21],ceng[21],where;
ll sha,eha;
struct node
{
ll sta[21];
ll pos,step;
node(){}
node(ll a[21],ll pos,ll step)
{
this->pos=pos;
for(ll i=0;i<21;i++)sta[i]=a[i];
this->step=step;
}
};
void change(ll a[21],ll f,ll &pos)
{
ll pceng=ceng[pos];
if(f==0)
{
ll dpos=pos-(pceng-1)-1;
if(dpos>=0&&ceng[dpos]==pceng-1)
{
swap(a[pos],a[dpos]);
pos=dpos;
}
}
if(f==1)
{
ll dpos=pos-(pceng-1);
if(dpos>=0&&ceng[dpos]==pceng-1)
{
swap(a[pos],a[dpos]);
pos=dpos;
}
}
if(f==2)
{
ll dpos=pos+(pceng);
if(dpos<21&&ceng[dpos]==pceng+1)
{
swap(a[pos],a[dpos]);
pos=dpos;
}
}
if(f==3)
{
ll dpos=pos+(pceng)+1;
if(dpos<21&&ceng[dpos]==pceng+1)
{
swap(a[pos],a[dpos]);
pos=dpos;
}
}
}
void bfs()
{
queue<node>fr;
queue<node>ba;
fr.push(node(s,where,0));
ba.push(node(e,0,0));
pp=Hash(s);
mp[pp]='1';
mpp[pp]=0;
pp=Hash(e);
if(mp[pp]=='1')
{
printf("0\n");
return ;
}
mp[pp]='2';
mpp[pp]=0;
while(!fr.empty()||!ba.empty())
{
node k;
if(!fr.empty())
{
for(ll i=0;i<4;i++)
{
k=fr.front();
if(k.step>=10)break;
change(k.sta,i,k.pos);
pp=Hash(k.sta);
if(mp[pp]=='1')continue;
if(mp[pp]=='2')
{
printf("%lld\n",k.step+1+mpp[pp]);
return ;
}
mp[pp]='1';
mpp[pp]=k.step+1;
k.step++;
fr.push(k);
}
fr.pop();
}
if(!ba.empty())
{
for(ll i=0;i<4;i++)
{
k=ba.front();
if(k.step>=10)break;
change(k.sta,i,k.pos);
pp=Hash(k.sta);
if(mp[pp]=='2')continue;
if(mp[pp]=='1')
{
printf("%lld\n",k.step+1+mpp[pp]);
return ;
}
mp[pp]='2';
mpp[pp]=k.step+1;
k.step++;
ba.push(k);
}
ba.pop();
}
}
printf("too difficult\n");
}
int main()
{
ll T;
scanf("%lld",&T);
while(T--)
{
mp.clear();
mpp.clear();
for(ll i=0;i<21;i++)
{
scanf("%lld",&s[i]);
if(s[i]==0)where=i;
}
ll k=0;
for(ll i=1;i<=6;i++)
for(ll j=1;j<=i;j++)
{
e[k]=i-1;
ceng[k]=i;
k++;
}
bfs();
}
}