• 八数码问题


    #pragma warning(disable:4786)
    #include<iostream>
    #include<set>
    #include<queue>
    #include<cmath>
    using namespace std;
    
    int gOrient[4][2] = {-1,0, 1,0, 0,-1, 0,1};
    
    //-----------------------------------------------------------------------------
    
    class State
    {
    public:
        int findPos(int n) const;
        bool operator < (const State& s) const;
        void print() const;
        void distance(int ans[]);
        void calHash();
        void calc(int ans[]);
    public:
        int a[9];
        int step;
        int dis;
        int hash;
    };
    
    //-----------------------------------------------------------------------------
    
    class EightFigure
    {
    public:
        EightFigure(int* init, int* ans = NULL);
        bool hasAnswer() const;
        void setInitState(int init[]);
        void setAnswer(int ans[]);
        void astar();
    private:
        int answer[9];
        set<int> calculated;
        priority_queue<State> states;
    };
    
    //-----------------------------------------------------------------------------
    
    int State::findPos(int n) const
    {
        for (int i=0; i<9; i++)
            if (a[i] == n)
                return i;
        return -1;
    }
    
    //优先队列默认大的优先,这里实际是求大于
    bool State::operator < (const State& s) const
    {
        return s.step + s.dis < step + dis;
    }
    
    void State::print() const
    {
        for (int i=0; i<9; i++)
        {
            if (i % 3 == 0)
                cout<<endl;
            cout<<a[i]<<' ';
        }
        cout<<endl;
    }
    
    void State::distance(int ans[])
    {
        dis = 0;
        for (int i=0; i<9; i++)
            dis += abs(ans[i]-a[i]);
    }
    
    void State::calHash()
    {
        int fac[] = {1,1,2,6,24,120,720,4050,40320};
        hash = 0;
        for (int i=0; i<9; i++)
        {
            int reverse = 0;
            for (int j=i+1; j<9; j++)
                if (a[j] < a[i])
                    reverse++;
            hash += reverse * fac[a[i]];
        }
    }
    
    void State::calc(int ans[])
    {
        step++;
        distance(ans);
        calHash();
    }
    
    //-----------------------------------------------------------------------------
    
    EightFigure::EightFigure(int* init, int* ans)
    {
        if (ans == NULL)
            for (int i=0; i<9; i++)
                answer[i] = i;
        else
            memcpy(answer, ans, 9*sizeof(int));
    
        State s;
        memcpy(s.a, init, 9*sizeof(int));
        s.step = 0;
        s.distance(ans);
        s.calHash();
    
        states.push(s);
        calculated.insert(s.hash);
    }
    
    //判断是否无解
    bool EightFigure::hasAnswer() const
    {
        State now = states.top();
        int reverseInit = 0, reverseAns = 0;
        for (int i=0; i<9; i++)
        {
            int countInit = 0, countAns = 0;
            for (int j=i+1; j<9; j++)
            {
                if (now.a[j] < now.a[i])
                    countInit++;
                if (answer[j] < answer[i])
                    countAns++;
            }
    
            reverseInit += countInit;
            reverseAns += countAns;
        }
    
        return reverseInit%2 == reverseAns%2;
    }
    
    void EightFigure::setAnswer(int ans[])
    {
        memcpy(answer, ans, 9*sizeof(int));
    }
    
    void EightFigure::astar()
    {
        if (!hasAnswer())
        {
            cout<<"无解
    ";
            return;
        }
    
        while (!states.empty())
        {
            State now = states.top();
            states.pop();
            now.print();
            if (now.dis == 0)
                break;
    
            int zero = now.findPos(0);
            int x = zero/3;
            int y = zero%3;
    
            for (int i=0; i<4; i++)
            {
                int xx = x + gOrient[i][0];
                int yy = y + gOrient[i][1];
                if (xx < 0 || xx >= 3 || yy < 0 || yy >= 3)
                    continue;
    
                State s = now;
                s.a[zero] = s.a[xx*3+yy];
                s.a[xx*3+yy] = 0;
                s.calc(answer);
    
                if (calculated.find(s.hash) == calculated.end())
                {
                    calculated.insert(s.hash);
                    states.push(s);
                }
            }
        }
    }
    
    //-----------------------------------------------------------------------------
    
    void main()
    {
        int init[9] = {3,5,1,2,8,6,7,4,0};
        int ans[] = {1,2,3,4,5,6,7,8,0};
        EightFigure eightFigure(init, ans);
        eightFigure.astar();
    }
  • 相关阅读:
    android studio 各种问题
    关于Android开发中Arm、X86和Mips(草稿)
    每日更新
    Error creating bean with name 'userRepository': Invocation of init method failed;
    API 'variant.getJavaCompiler()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'
    increase the minSdkVersion to 26
    Exception thrown on Scheduler.Worker thread. Add `onError` handling
    M600 Pro 安装问题解决
    Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed.
    大疆无人机M100相关问题解决过程
  • 原文地址:https://www.cnblogs.com/saieuler/p/3150706.html
Copyright © 2020-2023  润新知