hdu-1430 魔板 康拓展开+映射优化

给定三种操作,将排列A转化为排列B,求最少步骤。

这种题目可以只跑一次bfs,比如只跑"12345678",那么如果遇到"23456781"->某个字符串呢?因为每一个数字都是等价的,我们可以把2映射为1,3映射成2,以此类推。这样就可以用"12345678"跑出来的操作序列了。

#include <iostream>
#include <iomanip>
#include <set>
#include <cmath>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#define LL long long
using namespace std;
class cantor
{
public:
#define siz 8
    char c[siz]= {'1','2','3','4','5','6','7','8'};
    LL w[siz];
    bool vis[siz];
    cantor()
    {
        w[0]=1;
        for(int i=1; i<siz; i++)
            w[i]=w[i-1]*i;
    }
    void init()
    {
        for(int i=0; i<siz; i++)
            vis[i]=false;
    }
    LL makeCanto(string s)
    {
        init();
        LL rec=0;
        for(int i=0; i<siz; i++)
        {
            int d=0;
            for(int j=0; j<siz; j++)
            {
                if(vis[j])
                    continue;
                if(c[j]!=s[i])d++;
                else
                {
                    vis[j]=true;
                    break;
                }
            }
            rec+=w[siz-i-1]*d;
        }
        return rec;
    }
    string recover(LL val)
    {
        init();
        string s="";
        for(int i=siz-1; i>=0; i--)
        {
            LL te=val/w[i];
            val%=w[i];
            for(int j=0,cnt=-1; j<siz; j++)
            {
                if(vis[j])continue;
                else cnt++;
                if(cnt==te&&!vis[j])
                {
                    s+=c[j];
                    vis[j]=true;
                    break;
                }
            }
        }
        return s;
    }
} fix;
struct ax
{
    int _1,_2;
    ax(int __1,int __2)
    {
        _1=__1;
        _2=__2;
    }
    friend bool operator < (ax a,ax b)
    {
        if(a._1==b._1)
            return a._2<b._2;
        return a._1<b._2;
    }
};
LL n,m;
bool vis[50000];
bool f;
struct node
{
    LL v;
    string a;
    node(LL V,string A)
    {
        v=V;
        a=A;
    }
};
map<int,string> ans;
void bfs(int fr)
{
    queue<node> q;
    node ini=node(fr,"");
    q.push(ini);
    fill(vis,vis+50000,false);
    vis[fr]=true;
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        ans[now.v]=now.a;
        string nows=fix.recover(now.v);
        string nx;
        //A
        nx=nows;
        for(int i=0; i<4; i++)
            swap(nx[i],nx[i+4]);
        if(!vis[fix.makeCanto(nx)])
            vis[fix.makeCanto(nx)]=true,q.push(node(fix.makeCanto(nx),now.a+"A"));
        //B
        for(int i=0; i<4; i++)
            nx[(i+1)%4]=nows[i],nx[4+(i+1)%4]=nows[4+i];
        if(!vis[fix.makeCanto(nx)])
            vis[fix.makeCanto(nx)]=true,q.push(node(fix.makeCanto(nx),now.a+"B"));
        //C
        nx=nows;
        nx[1]=nows[5];nx[2]=nows[1];
        nx[6]=nows[2];nx[5]=nows[6];
        if(!vis[fix.makeCanto(nx)])
            vis[fix.makeCanto(nx)]=true,q.push(node(fix.makeCanto(nx),now.a+"C"));
    }
}
int main()
{
    cin.sync_with_stdio(false);

    string s1,s2;
    /*
    string nows,nx;
    cin>>nows;

    nx=nows;
    nx[1]=nows[5];nx[2]=nows[1];
    nx[6]=nows[2];nx[5]=nows[6];
    nows=nx;
    nx[1]=nows[5];nx[2]=nows[1];
    nx[6]=nows[2];nx[5]=nows[6];
    cout<<nx<<endl;
    */
    string fuck="12348765";
    bfs(fix.makeCanto(fuck));
    while(cin>>s1>>s2)
    {
        reverse(s1.begin()+4,s1.end());
        reverse(s2.begin()+4,s2.end());
        for(int i=0;i<8;i++)
        {
            int d;
            for(int j=0;j<8;j++)
                if(s2[i]==s1[j])
                    d=j;
            s2[i]=fuck[d];
        }
        cout<<ans[fix.makeCanto(s2)]<<endl;

    }
}
原文地址:https://www.cnblogs.com/LukeStepByStep/p/8433598.html