• 洛谷


    为什么估价是16,因为最后一步复原空格可以恢复两个位置,当然设成17、18都可以。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    
    struct State {
        char g[5][6];                   //矩阵的状态,0是白马,1是黑马,规定空格是*
        int hstep;                      //step+估价函数,至少需要的步数
    
        State() {}
        int h();                        //估价函数h,为未归位的骑士数
        void move_to(int id,int step);  //尝试移动状态加入优先队列
    
        bool operator==(const State& s)const {
            //无序map
            for(int i=0; i<5; i++)
                for(int j=0; j<5; j++)
                    if(g[i][j]!=s.g[i][j])
                        return false;
            return true;
        }
    
        bool operator<(const State& s)const {
            //最大堆
            return hstep>s.hstep;
        }
    
    } s_state,t_state;
    
    struct State_Hash {
        size_t operator()(const State&t)const {
            int id=0;
            for(int i=0; i<5; i++)
                for(int j=0; j<5; j++)
                    id=(id<<1)+(t.g[i][j]-'0');
            return id;
        }
    };
    
    int State::h() {
        //估价函数,因为每次移动的是空格
        int res=0;
        for(int i=0; i<5; i++)
            for(int j=0; j<5; j++)
                if(g[i][j]!=t_state.g[i][j])
                    res++;
        return res;
    }
    
    
    //vis从起点开始找到的状态
    unordered_map<State,int,State_Hash> vis;
    priority_queue<State> pq;
    
    int dx[]= {2,1,-1,-2,-2,-1,1,2};
    int dy[]= {1,2,2,1,-1,-2,-2,-1};
    
    
    void State::move_to(int id,int step) {
        //空格向id方向移动
        int ox=-1;
        int oy=-1;
    
        for(int i=0; i<5; i++) {
            for(int j=0; j<5; j++) {
                if(g[i][j]=='*') {
                    ox=i,oy=j;
                    break;
                }
            }
        }
    
        int nx=ox+dx[id];
        int ny=oy+dy[id];
    
        //越界
        if(nx<0||ny<0||nx>4||ny>4)
            return;
    
        State res=*this;
        swap(res.g[ox][oy],res.g[nx][ny]);
    
        res.hstep=step+1+res.h();
    
        if(hstep>16)
            return;
    
        if(vis.count(res)) {
            return;
        } else {
            vis[res]=step+1;
            pq.push(res);
        }
    }
    
    
    
    //单向A*搜索
    bool A_star() {
        vis.clear();
        while(!pq.empty())
            pq.pop();
    
        vis[s_state]=0;
        pq.push(s_state);
        while(!pq.empty()) {
            State curstate=pq.top();
            pq.pop();
            int curstep=vis[curstate];
            for(int i=0; i<8; i++)
                curstate.move_to(i,curstep);
            if(vis.count(t_state))
                return true;
        }
        return false;
    }
    
    
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in","r",stdin);
    #endif // Yinku
        strcpy(t_state.g[0],"11111");
        strcpy(t_state.g[1],"01111");
        strcpy(t_state.g[2],"00*11");
        strcpy(t_state.g[3],"00001");
        strcpy(t_state.g[4],"00000");;
    
        int T;
        scanf("%d",&T);
        while(T--) {
            for(int i=0; i<5; i++)
                scanf("%s",s_state.g[i]);
    
            if(A_star()) {
                int ans=vis[t_state];
                printf("%d
    ",ans>15?-1:ans);
            } else {
                puts("-1");
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    Scrapy 扩展中间件: 针对特定响应状态码,使用代理重新请求
    Scrapy 扩展中间件: 同步/异步提交批量 item 到 MySQL
    Scrapy 隐含 bug: 强制关闭爬虫后从 requests.queue 读取的已保存 request 数量可能有误
    Scrapyd 改进第二步: Web Interface 添加 STOP 和 START 超链接, 一键调用 Scrapyd API
    简单示例理解神闭包
    ejs 模板使用方法
    我使用的开源组件汇总,以备学习使用
    了不起的Node.js--之五 TCP连接
    Windows7下Java运行时环境搭建
    了不起的Node.js--之四
  • 原文地址:https://www.cnblogs.com/Yinku/p/10978329.html
Copyright © 2020-2023  润新知