A*算法:P5507 机关 题解

题目入口

这个题有很多解法,比如双向广搜。现在使用A*算法,这个算法属于启发式搜索的一类。

对于一个状态x设从起点到这个状态的代价是g(x),设h*(x)为理想情况下从x到终点的代价的估计值。注意这个值一定是理想状态下的,一定不会大于最终的实际距离。

设f*(x)=g(x)+h*(x)为状态的估值函数,在搜索时,找到f*值最小的状态(优先队列),优先对其进行搜索,配合最优性枝剪,可以有效地剪去较差分枝,提高算法效率。

对于这道题,g(x)就是已走的步数,h*(x)可设计为转到目标状态的步数除以2,因为在理想情况下转一次按钮有可能会让另一个按钮也想目标状态转一次。当然,在绝大部分时候,h(x)要远大于 h*(x),所以可以考虑给h*(x)加上系数,让它更逼近真实的步数,至于这个系数要有多大,就是比较玄学的事情了,太大有可能会出错,太小程序有可能会超时。

程序本身是BFS算法,不过使用的是优先队列维护优先级,f*(x)小的优先。从初始状态开始,扩展到下一个状态时发现目标状态,则可以直接输出结果;计算对应的f*(x),放入优先队列中。接着从优先队列中找到f*(x)最小的状态来进行扩展。

看上去挺复杂的,其实就比常规的BFS多了几行代码,代码如下:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1<<24;
int g[N],nxt[14][6],fa[N],ans[30],choice[N];
struct node{
    int state;
    double F;
    node(int s):state(s){
        double h=0;
        F=0;
        for(int i=0;i<=11;i++)
            if((s>>(i<<1))&3)
                h+=4-((s>>(i<<1))&3);
        F=h*0.6+g[s];//给h加的系数,多次测试发现系数在0.6到1.1之间可以过全部检查点
    }
    bool operator<(const node &y)const{
        return F>y.F;
    }
};
priority_queue<node>q;
int main (){
    int button,Start=0;
    for(int i=0;i<=11;i++){
        cin>>button;
        Start|=(button-1)<<(i<<1);
        for(int j=0;j<=3;j++){
            int x;
            cin>>x;
            nxt[i][j]=x-1;
        }
    }
    q.push(node(Start));
    g[Start]=0;
    while(!q.empty()){
        int state=q.top().state;
        q.pop();
        if(state==0) break;//到达结果
        int si,sNxt,nx,nextState;
        for(int i=0;i<=11;i++){
            si=(state>>(i<<1))&3;//第i个按钮的状态
            nx=nxt[i][si];
            sNxt=(state>>(nx<<1))&3;//受牵连的按钮
            nextState = state ^ (si << (i << 1)) ^ (((si + 1) & 3) << (i << 1)) ^ (sNxt << (nx << 1)) ^ (((sNxt + 1) & 3) << (nx << 1));//旋转后的状态
            if(!g[nextState]){//如果没走过,更新状态
                g[nextState]=g[state]+1;
                fa[nextState]=state;
                choice[nextState]=i+1;
                q.push(node(nextState));
            }
        }
    }
    int cnt=0,state=0;
    while(state!=Start){//回溯
        ans[++cnt]=choice[state];
        state=fa[state];
    }
    cout<<cnt<<endl;
    for(int i=cnt;i;i--)
        cout<<ans[i]<<" ";
    return 0;
}
相关推荐
小O的算法实验室15 小时前
2026年ASOC,基于深度强化学习的无人机三维复杂环境分层自适应导航规划方法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
郭涤生16 小时前
STL vector 扩容机制与自定义内存分配器设计分析
c++·算法
༾冬瓜大侠༿16 小时前
vector
c语言·开发语言·数据结构·c++·算法
Ricky111zzz16 小时前
leetcode学python记录1
python·算法·leetcode·职场和发展
汀、人工智能16 小时前
[特殊字符] 第58课:两个正序数组的中位数
数据结构·算法·数据库架构··数据流·两个正序数组的中位数
liu****16 小时前
第16届省赛蓝桥杯大赛C/C++大学B组(京津冀)
开发语言·数据结构·c++·算法·蓝桥杯
汀、人工智能16 小时前
[特殊字符] 第79课:分割等和子集
数据结构·算法·数据库架构·位运算·哈希表·分割等和子集
汀、人工智能16 小时前
[特殊字符] 第74课:完全平方数
数据结构·算法·数据库架构·图论·bfs·完全平方数
CoderCodingNo16 小时前
【GESP】C++四、五级练习题 luogu-P1177 【模板】排序
数据结构·c++·算法
Proxy_ZZ017 小时前
从零实现LDPC比特翻转译码器:C语言实战与底层逻辑解析
c语言·算法