HDU 3567 Eight II BFS预处理

题意:就是八数码问题,给你开始的串和结束的串,问你从开始到结束的最短且最小的变换序列是什么

分析:我们可以预处理打表,这里的这个题可以和HDU1430魔板那个题采取一样的做法

预处理打表,因为八数码问题实际上是每个小块位置的变化,上面的数字只是用来标记位置的,

所以通过映射将初末序列进行置换就好了,然后因为每次的x字符的置换位置不一样

所以需要以123456789这个初始串打9遍表就好了733ms

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <queue>
using namespace std;
const int N=5005;
int fac[]= {1,1,2,6,24,120,720,5040,40320,362880};
int aim;
int cantor(char s[])
{
    int ans=0;
    for(int i=1,j=8; i<=9; ++i,--j)
    {
        int tmp=0;
        for(int k=i+1; k<=9; ++k)
            if(s[i]>s[k])++tmp;
        ans+=(tmp*fac[j]);
    }
    return ans;
}
struct Node
{
    char s[10];
    int hs;
};
struct asd
{
   bool vis;
   char c;
   int pre;
}o[10][362880];
queue<Node>q;
void bfs(int pos)
{
    Node a;
    for(int i=1; i<=9; ++i)
        a.s[i]='0'+i;
    aim=a.hs=cantor(a.s);
    o[pos][a.hs].vis=1;
    q.push(a);
    while(!q.empty())
    {
        a=q.front();
        q.pop();
        int now=a.hs;
        int x;
        for(int i=1; i<=9; ++i)
            if(a.s[i]=='0'+pos)x=i;
        if(x+3<10)
        {
            bool flag=0;
            swap(a.s[x],a.s[x+3]);
            a.hs=cantor(a.s);
            if(o[pos][a.hs].vis)
                flag=1;
            if(!flag)
            {
                o[pos][a.hs].vis=1;
                o[pos][a.hs].c='d';
                o[pos][a.hs].pre=now;
                q.push(a);
            }
            swap(a.s[x],a.s[x+3]);
        }
        if(x%3!=1)
        {
            bool flag=0;
            swap(a.s[x],a.s[x-1]);
            a.hs=cantor(a.s);
            if(o[pos][a.hs].vis)
                flag=1;
            if(!flag)
            {
                o[pos][a.hs].vis=1;
                o[pos][a.hs].c='l';
                o[pos][a.hs].pre=now;
                q.push(a);
            }
            swap(a.s[x],a.s[x-1]);
        }
        if(x%3)
        {
            bool flag=0;
            swap(a.s[x],a.s[x+1]);
            a.hs=cantor(a.s);
           if(o[pos][a.hs].vis)
                flag=1;
            if(!flag)
            {
                o[pos][a.hs].vis=1;
                o[pos][a.hs].c='r';
                o[pos][a.hs].pre=now;
                q.push(a);
            }
            swap(a.s[x],a.s[x+1]);
        }
        if(x-3>0)
        {
            bool flag=0;
            swap(a.s[x],a.s[x-3]);
            a.hs=cantor(a.s);
           if(o[pos][a.hs].vis)
                flag=1;
            if(!flag)
            {
                o[pos][a.hs].vis=1;
                o[pos][a.hs].c='u';
                o[pos][a.hs].pre=now;
                q.push(a);
            }
            swap(a.s[x],a.s[x-3]);
        }
    }
}
char s[15],t[15];
string res;
void getres(int u,int pos)
{
    while(u!=aim)
    {
       res=res+o[pos][u].c;
       u=o[pos][u].pre;
    }
}
char mat[13];
int main()
{
    for(int i=0;i<326880;++i)
     for(int j=1;j<=9;++j)
      o[j][i].vis=0;
    for(int i=1;i<=9;++i)
       bfs(i);
    int T,cas=0;
    scanf("%d",&T);
    while(T--)
    {
         scanf("%s%s",s+1,t+1);
         int flag;
         for(int i=1;i<=9;++i)
         {
             if(s[i]=='X')s[i]='9',flag=i;
             if(t[i]=='X')t[i]='9';
             mat[s[i]-'0']=i+'0';
         }
         for(int i=1;i<=9;++i)
            t[i]=mat[t[i]-'0'];
        int ans=cantor(t);
        res.clear();
        getres(ans,flag);
        printf("Case %d: %d
",++cas,res.size());
        reverse(res.begin(),res.end());
        cout<<res<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5252053.html