根据汉诺塔的特点找到保存状态的最简方式。懂得hash的真谛才能ac qaq
首先从有序状态可以推出所有有解状态。大体是给每个不同的数字以不同的模,根据他们的位置分别哈希,加起来作为该种状态的哈希值。
这样可以根据这个哈希值取得各个数字的位置,得到当前情况。打表出各种移动的所需要的代价,即可转移到下一个状态
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=20000008;
int mp7[maxn];
int mp6[maxn>>1];
int mp5[maxn>>2];
int mp4[maxn>>3];
int mp3[maxn>>4];
int dp[10][10];
void bfs(int ha,int mp[],int mod)
{
queue<int> q;
queue<int> p;
q.push(ha);
p.push(0);
mp[ha]=0;
int i,a[10],b[10];
int x,y,sx,idx,nx,ny;
while(!q.empty())
{
x=q.front();q.pop();
y=p.front();p.pop();
sx=x;idx=0;
for(i=1;i<=mod;i++)
{
a[i]=sx%mod;
sx/=mod;
}
memset(b,INF,sizeof(b));
for(i=1;i<=mod;i++)
if(b[a[i]+1]>i)
b[a[i]+1]=i;
b[0]=0;b[mod+1]=0;
for(i=1;i<=mod;i++)
{
if(b[i]==INF) continue;
if(b[i]<b[i-1])
{
nx=x-dp[mod][b[i]];
if(mp[nx]==-1)
{
ny=y+1;
mp[nx]=ny;
q.push(nx);
p.push(ny);
}
}
if(b[i]<b[i+1])
{
nx=x+dp[mod][b[i]];
if(mp[nx]==-1)
{
ny=y+1;
mp[nx]=ny;
q.push(nx);
p.push(ny);
}
}
}
}
}
void init()
{
int i,j;
memset(mp3,-1,sizeof(mp3));
memset(mp4,-1,sizeof(mp4));
memset(mp5,-1,sizeof(mp5));
memset(mp6,-1,sizeof(mp6));
memset(mp7,-1,sizeof(mp7));
for(i=3;i<=7;i++)
{
dp[i][1]=1;
for(j=2;j<=i;j++)
dp[i][j]=dp[i][j-1]*i;
}
int ans=1;
int mod;
int md[10];
md[1]=1;
for(i=3;i<=7;i++)
{
mod=i;
ans=0;
for(j=2;j<=i;j++)
md[j]=md[j-1]*mod;
for(j=i;j>=1;j--)
ans=ans+(j-1)*md[i-j+1];
if(i==3) bfs(ans,mp3,mod);
if(i==4) bfs(ans,mp4,mod);
if(i==5) bfs(ans,mp5,mod);
if(i==6) bfs(ans,mp6,mod);
if(i==7) bfs(ans,mp7,mod);
}
}
struct shit{
int x,y;
bool operator<(const shit &a) const// "This blade never gets any lighter."
{
return x<a.x;
}
}f[10];
int main()
{
int i,j,n,m,t;
init();
int b[9];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&f[i].x);
f[i].y=i;
}
if(n==1) printf("0
");
else if(n==2)
{
if(f[1].x<f[2].x) printf("0
");
else printf("-1
");
}
else
{
sort(f+1,f+1+n);
for(i=1;i<=n;i++)
b[f[i].y]=i;
int md[10];
md[1]=1;
for(i=2;i<=n;i++)
md[i]=md[i-1]*n;
int ans=0;
for(i=1;i<=n;i++)
ans+=(n-i)*md[b[i]];
if(n==3) printf("%d
",mp3[ans]);
if(n==4) printf("%d
",mp4[ans]);
if(n==5) printf("%d
",mp5[ans]);
if(n==6) printf("%d
",mp6[ans]);
if(n==7) printf("%d
",mp7[ans]);
}
}
return 0;
}