zoukankan      html  css  js  c++  java
  • hdu-1043 bfs+康拓展开hash

    因为是计算还原成一种局面的最短步骤,应该想到从最终局面开始做bfs,把所有能到达的情况遍历一遍,把值存下来。

    bfs过程中,访问过的局面的记录是此题的关键,9*9的方格在计算过程中直接存储非常占内存。而这个显然是12345678x的不同排列,考虑康拓展开来记录,每个局面hash成一个整数。步骤我先算了一下,最多有31步,我用4进制位hash成了两个整数来保存

    #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 9
        char c[siz]={'1','2','3','4','5','6','7','8','x'};
        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-=e*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;
        }
    };
    LL n,m;
    char mp[3][3];
    set<LL> s;
    string ss="";
    const string las="12345678x";
    bool f;
    int dir[4][2]={-1,0,1,0,0,1,0,-1};
    char dfuck[4]={'d','u','l','r'};
    struct node
    {
        LL s;
        int c;
        int x,y;
        LL a,b;
        node(LL ss,int aa,int X,int Y,LL A,LL B){s=ss;c=aa;x=X;y=Y;a=A;b=B;}
    };
    struct ax
    {
        LL a,b,c;
        ax(LL A,LL B,LL C){a=A;b=B;c=C;}
        ax(){}
    };
    map<LL,ax> ans;
    LL bit[18];
    int main()
    {
        cin.sync_with_stdio(false);
        cantor fx;
        bit[0]=1;
        for(int i=1;i<18;i++)
            bit[i]=bit[i-1]*4;
        queue<node> q;
        node ini=node(fx.makeCanto(las),0,2,2,0,0);
        q.push(ini);
        s.clear();
        ans.clear();
        int mx=0;
        s.insert(fx.makeCanto(las));
        while(!q.empty())
        {
            node now=q.front();
            ans[now.s]=ax(now.a,now.b,now.c);
            q.pop();
            mx=max(now.c,mx);
            for(int i=0;i<4;i++)
            {
                int yy=now.y+dir[i][0];
                int xx=now.x+dir[i][1];
                if(xx<0||yy<0||xx>=3||yy>=3)continue;
                string nx=fx.recover(now.s);
                swap(nx[now.y*3+now.x],nx[yy*3+xx]);
                LL nxv=fx.makeCanto(nx);
                if(s.find(nxv)!=s.end())continue;
                s.insert(nxv);
                LL na=now.a,nb=now.b;
                if(now.c<16)
                {
                    na+=i*bit[now.c];
                }
                else
                {
                    nb+=i*bit[now.c-16];
                }
                q.push(node(nxv,now.c+1,xx,yy,na,nb));
            }
        }
        while(cin>>mp[0][0]>>mp[0][1]>>mp[0][2]>>mp[1][0]>>mp[1][1]>>mp[1][2]>>mp[2][0]>>mp[2][1]>>mp[2][2])
        {
            int x,y;
            f=false;
            s.clear();
            ss="";
            for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                {
                    ss+=mp[i][j];
                    if(mp[i][j]=='x')
                        y=i,x=j;
                }
            string o="";
            if(ss=="12345678x")
            {
                cout<<"lr"<<endl;
                continue;
            }
            if(ans.find(fx.makeCanto(ss))==ans.end())
            {
                cout<<"unsolvable"<<endl;
                continue;
            }
            ax fuck=ans[fx.makeCanto(ss)];
            for(int i=0;i<fuck.c;i++)
            {
                if(i<16)
                {
                    o+=dfuck[fuck.a%4];
                    fuck.a/=4;
                }
                else
                {
                    o+=dfuck[fuck.b%4];
                    fuck.b/=4;
                }
            }
            reverse(o.begin(),o.end());
            cout<<o<<endl;
        }
    }

  • 相关阅读:
    SpringCloud之初入江湖
    消息中间件RabbitMQ
    分布式搜索引擎ElasticSearch
    MongoDB简介
    SpringBoot和SpringCloud版本对应
    终于有人把Elasticsearch原理讲透了!
    nginx不停服,重新加载配置
    小程序自定义头部标题栏并且自适应各种手机屏幕(滚动头部渐隐渐现)
    Navicat链接数据库报错1130解决方案
    传统的小程序登录 和 云开发小程序登录
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/8433420.html
Copyright © 2011-2022 走看看