#1539 : 数组重排3
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
2 54321 321
样例输出
-
3 -1
描述
给定一个{1..N}的排列A1, A2, ... AN,每一次操作可以将相邻的两个数一起移动(保持两个数相邻且前后顺序不变)到任意位置。询问至少经过多少次操作,可以使得原序列变为1, 2, ..., N。
例如对于54321,把32一起移动到最左端得到32541;再把25一起移动到最右端得到34125;再把12一起移动到最左端得到12345。
输入
第1行:1个正整数 T,表示输入数据的组数
第2..T+1行:每行一个字符串,表示初始排列
对于30%的数据:T = 1, 1 ≤ N ≤ 5
对于100%的数据:1 ≤ T ≤ 5, 1 ≤ N ≤ 8
输出
第1..T行:每行一个整数,第i行表示第i个排列变化为1, 2, ..., N所需要的最少步数。若无可行方案,输出"-1"。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cmath>
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+7;
typedef long long LL;
struct node
{
int a[10], step=0, x;
} p;
int b[10];
map<int,int>mp;
int bfs(int x)
{
queue<node>q;
mp.clear();
node tmp;
int k=0;
tmp.x=x;
while(x)
{
tmp.a[++k]=x%10;
b[k]=x%10;
x/=10;
}
for(int i=1; i<=k/2; i++) swap(tmp.a[i],tmp.a[k-i+1]);
sort(b+1,b+k+1);
int y=0;
for(int i=1; i<=k; i++) y=y*10+b[i];
tmp.step=0;
q.push(tmp);
while(!q.empty())
{
tmp=q.front();
q.pop();
int u=tmp.x;
if(u==y) return tmp.step;
mp[u]=1;
for(int i=1; i<k; i++)
{
for(int j=1; j<k; j++)
{
if(i==j) continue;
int cnt=1, sum=0;
node tmp1=tmp;
tmp1.step=tmp.step+1;
for(int h=1; h<=k; h++)
{
if(cnt==j)
{
sum=sum*10+tmp.a[i];
sum=sum*10+tmp.a[i+1];
tmp1.a[cnt]=tmp.a[i];
tmp1.a[++cnt]=tmp.a[i+1];
cnt++;
}
if(h==i||h==i+1) continue;
sum=sum*10+tmp.a[h];
tmp1.a[cnt]=tmp.a[h];
cnt++;
}
if(cnt==j)
{
sum=sum*10+tmp.a[i];
sum=sum*10+tmp.a[i+1];
tmp1.a[cnt]=tmp.a[i];
tmp1.a[++cnt]=tmp.a[i+1];
cnt++;
}
if(mp.count(sum)) continue;
if(sum==y) return tmp1.step;
mp[sum]=1,tmp1.x=sum;
q.push(tmp1);
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int x;
scanf("%d", &x);
cout<<bfs(x)<<endl;
}
return 0;
}