每三位代表第i个格子的目前位置 这三位为0代表没这个数
然后最多7个数 也就是 8^7 约等于 400000 所有从终点到起点反向预处理
学到的技巧
数据量不大要先想到搜索
如果感觉这时搜索会超时可以考虑预处理什么的
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
using namespace std;
int vis[5000000];
int a[15], b[15];
int eight[11];
void bfs(int am)
{
int x = 0, pre = 1;
for(int i = 1; i <= am; i++)
{
x += pre * i;
pre *= 8;
}
vis[x] = 0;
queue<int>qu;
qu.push(x);
// printf("%d\n", x);
while(qu.size())
{
x = qu.front();
//printf("%d\n", x);
qu.pop();
int xx = x, po[10];
for(int i = 1; i <= am; i++)
{
po[i] = xx % 8;
xx /= 8;
}
int flag[10] = {0};
for(int i = 1; i <= am; i++)
if(flag[po[i]] == 0)
{
flag[po[i]] = 1;
int Po = po[i];
int prel = 1000;
int prer = 1000;
for(int j = 1; j <= am; j++)
if(po[j] == Po - 1)
{
prel = min(prel, j);
}
else if(po[j] == Po + 1)
{
prer = min(prer, j);
}
// printf("%d %d %d\n",i, prel, prer);
if(po[i] + 1 <= am && prer > i)
{
int xx = x;
xx -= po[i] * eight[i];
xx += (po[i] + 1)* eight[i];
// printf("%d**\n", xx);
if(vis[xx] == -1)
{
vis[xx] = vis[x] + 1;
qu.push(xx);
}
}
if(po[i] - 1 >= 1 && prel > i)
{
int xx = x;
xx -= po[i] * eight[i];
xx += (po[i] - 1) * eight[i];
//printf("%d!!\n", xx);
if(vis[xx] == -1)
{
vis[xx] = vis[x] + 1;
qu.push(xx);
}
}
}
}
}
int main()
{
eight[1] = 1;
for(int i = 2; i <= 9; i++) eight[i] = 8 * eight[i - 1];
memset(vis, -1, sizeof(vis));
for(int i = 1; i <= 7; i++) bfs(i);
int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + 1 + n);
for(int i = 1; i <= n; i++)
{
a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
//printf("%d\n", a[i]);
}
int sym = 0, po[15], pre = 1;
for(int i = 1; i <= n; i++) po[a[i]] = i;
for(int i = 1; i <= n; i++)
{
sym += po[i] * pre;
pre *= 8;
}
//printf("%d\n", sym);
printf("%d\n", vis[sym]);
}
return 0;
}