zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    自我介绍
    自动生成小学生四则运算(C语言)
    黄金点游戏
    7/5linux命令(整理中)
    第二章内容及作业
    第三章笔记
    第一章作业
    第一阶段笔记整理7.23
    第三章课后作业
    7/6linux命令
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5252053.html
Copyright © 2011-2022 走看看