汉诺塔升级版(搜索)

汉诺塔升级版

题目描述:
汉诺塔升级了:现在我们有?个圆盘和?个柱子,每个圆盘大小都不一样,
大的圆盘不能放在小的圆盘上面,?个柱子从左到右排成一排。每次你可以将一个柱子上的最上面的圆盘移动到右边或者左边的柱子上(如果移动之后是合法的话)。现在告诉你初始时的状态, 你希望用最少的步数将第?大的盘子移动到第?根柱子上,问最小步数。
输入格式:
第一行一个正整数?,代表询问的组数。
接下来?组数据,每组数据第一行一个整数?。
接下来一行每行?个正整数,代表每个柱子上圆盘的大小。
输出格式:
输出共?行,代表每次的答案。如果方案不存在,输出“−1” 。
样例输入:
4
3
2 1 3
2
7 8
2
10000 1000
3
97 96 95
样例输出:
4
0
-1
20
样例解释:
无。
数据范围与规定:
对于70%的数据,N的值都是相等的。
对于100%的数据,1≤N≤6×10^3 ,1≤N≤7。

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=8000000;
int T,n,b[10],c[10],top[10],s[maxn],p[maxn],m[10],S[maxn];
queue<int> q;
bool flag[maxn];
struct node
{
    int x;
    int id;
    bool operator < (node a)const
    {
        return x<a.x;
    }
}a[10];
void insert(int s)
{
    memset(top,0,sizeof(top));
    int len=0,tmp=s;
    while(tmp)
    {
        p[++len]=tmp%10;
        tmp/=10;
    }
    reverse(p+1,p+len+1);
    for(int i=len;i>=1;i--)
    top[p[i]]=i;
    for(int i=1;i<=len;i++)
    if(i==top[p[i]])
    {
        if(p[i]!=1&&(top[p[i]-1]>i||!top[p[i]-1]))
        {
            int r=s-m[len-i];
            if(!flag[r])
            {
                flag[r]=1;
                S[r]=S[s]+1;
                q.push(r);
            }
        }
        if(p[i]!=len&&(top[p[i]+1]>i||!top[p[i]+1]))
        {
            int r=s+m[len-i];
            if(!flag[r])
            {
                flag[r]=1;
                S[r]=S[s]+1;
                q.push(r);
            }
        }
    }
}
void ready()
{
    int s=0;m[0]=1;
    for(int i=1;i<=7;i++)
    {
        m[i]=m[i-1]*10;
        s=s*10+i;
        q.push(s);
        flag[s]=1;S[s]=0;
    }
    while(!q.empty())
    {
        s=q.front();
        q.pop();
        insert(s);
    }
}
int main()
{
    ready();
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i].x;
            a[i].id=i;
        }
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++)
        b[a[i].id]=i;
        for(int i=1;i<=n;i++)
        c[b[i]]=i;
        int s=0;
        for(int i=1;i<=n;i++)
        s=s*10+c[i];
        if(flag[s]==0) cout<<-1<<endl;
        else cout<<S[s]<<endl;
    }
    return 0;
}
posted @ 2016-10-04 21:04  抽空的太阳  阅读(158)  评论(0编辑  收藏  举报