sicily_1150 & sicily_1151

宽搜 + 康托展开
两题其实是一样的两道题,可以训练宽搜,但是,这两题作为宽搜其实是水题,比较难的地方其实是对状态的记录,即队列的元素采用什么来保存,这里用到了康托展开(介绍点这儿)
解决了保存的问题,接下来的都是琐事了,上代码:

//sicily 1150 简单魔板
#include <bits/stdc++.h>

using namespace std;

int n,m,goal,tmp[10],v[10];
int factor[]={1,1,2,6,24,120,720,5040,40320,362880};

struct node{
    int val;
    string str;
    node(int val=0,string st=""):val(val),str(st){}
};

int cantor(){
    int sum=0;
    for(int i=0;i<n;i++)
    {
        int cnt=0;
        for(int j=i+1;j<n;j++)
            if(tmp[j]<tmp[i])
                cnt++;
        sum+=cnt*factor[n-i-1];
    }
    return sum+1;
}

void inv_cantor(int num)
{
    num--;
    memset(v,0,sizeof(v));
    for(int i=0;i<n;i++)
    {
        int index=num/factor[n-i-1],j=1;
        for(j=1;j<=n;j++)
            if(!v[j])
            {
                if(!index)
                    break;
                index--;
            }
        tmp[i]=j,v[j]=1;
        num%=factor[n-i-1];
    }
}

void print()
{
    for(int i=0;i<8;i++)
        cout<<tmp[i];
    cout<<endl;
}

int A(int num)
{
    inv_cantor(num);
    for(int i=0;i<4;i++)
        swap(tmp[i],tmp[i+4]);
    return cantor();
}

int B(int num)
{
    inv_cantor(num);
    tmp[8]=tmp[3],tmp[9]=tmp[7];
    for(int i=2;i>=0;i--)
        tmp[i+1]=tmp[i];
    for(int i=6;i>=4;i--)
        tmp[i+1]=tmp[i];
    tmp[0]=tmp[8],tmp[4]=tmp[9];
    return cantor();
}

int C(int num)
{
    inv_cantor(num);
    tmp[8]=tmp[1];
    tmp[1]=tmp[5],tmp[5]=tmp[6],tmp[6]=tmp[2];
    tmp[2]=tmp[8];
    return cantor();
}

int main()
{
    n=8;
    string a="A",b="B",c="C";
    while(cin>>m&&m>=0)
    {
        for(int i=0;i<n;i++)
            cin>>tmp[i];
        goal=cantor();

        queue<node> q;
        q.push(node(24,""));

        node front;
        while(!q.empty())
        {
            front=q.front();
            q.pop();
            if(front.val==goal)
                break;
            if(front.str.size()>10)
            {
                front=node(-1,"");
                break;
            }
            q.push(node(A(front.val),front.str+a));
            q.push(node(B(front.val),front.str+b));
            q.push(node(C(front.val),front.str+c));
        }

        if(front.val==-1)
            cout<<-1<<endl;
        else
            cout<<front.str.size()<<" "<<front.str<<endl;
    }

    return 0;
}                                 

加个剪枝就变成了第二题的代码:

//sicily 1151 魔板
#include <bits/stdc++.h>

using namespace std;

int n,m,goal,tmp[10],v[10],vis[45005];
int factor[]={1,1,2,6,24,120,720,5040,40320,362880};

struct node{
    int val;
    string str;
    node(int val=0,string st=""):val(val),str(st){}
};

int cantor(){
    int sum=0;
    for(int i=0;i<n;i++)
    {
        int cnt=0;
        for(int j=i+1;j<n;j++)
            if(tmp[j]<tmp[i])
                cnt++;
        sum+=cnt*factor[n-i-1];
    }
    return sum+1;
}

void inv_cantor(int num)
{
    num--;
    memset(v,0,sizeof(v));
    for(int i=0;i<n;i++)
    {
        int index=num/factor[n-i-1],j=1;
        for(j=1;j<=n;j++)
            if(!v[j])
            {
                if(!index)
                    break;
                index--;
            }
        tmp[i]=j,v[j]=1;
        num%=factor[n-i-1];
    }
}

void print()
{
    for(int i=0;i<8;i++)
        cout<<tmp[i];
    cout<<endl;
}

int A(int num)
{
    inv_cantor(num);
    for(int i=0;i<4;i++)
        swap(tmp[i],tmp[i+4]);
    return cantor();
}

int B(int num)
{
    inv_cantor(num);
    tmp[8]=tmp[3],tmp[9]=tmp[7];
    for(int i=2;i>=0;i--)
        tmp[i+1]=tmp[i];
    for(int i=6;i>=4;i--)
        tmp[i+1]=tmp[i];
    tmp[0]=tmp[8],tmp[4]=tmp[9];
    return cantor();
}

int C(int num)
{
    inv_cantor(num);
    tmp[8]=tmp[1];
    tmp[1]=tmp[5],tmp[5]=tmp[6],tmp[6]=tmp[2];
    tmp[2]=tmp[8];
    return cantor();
}

int main()
{
    n=8;
    string a="A",b="B",c="C";
    while(cin>>m&&m>=0)
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            cin>>tmp[i];
        goal=cantor();

        queue<node> q;
        q.push(node(24,""));

        node front;
        v[24]=1;
        while(!q.empty())
        {
            front=q.front();
            q.pop();
            if(front.val==goal)
                break;

            if(front.str.size()>m)
            {
                front=node(-1,"");
                break;
            }

            if(!vis[A(front.val)]) q.push(node(A(front.val),front.str+a));
            if(!vis[B(front.val)]) q.push(node(B(front.val),front.str+b));
            if(!vis[C(front.val)]) q.push(node(C(front.val),front.str+c));
            vis[A(front.val)]=1;
            vis[B(front.val)]=1;
            vis[C(front.val)]=1;
        }

        if(front.val==-1)
            cout<<-1<<endl;
        else
            cout<<front.str.size()<<" "<<front.str<<endl;
    }

    return 0;
}                                 

你可能感兴趣的:(sicily_1150 & sicily_1151)