A * search algorithm magic

A*

A * is a heuristic search algorithm, also known as the best graph search algorithm.

What is a heuristic search?

As we all know, the computer at the time of the search algorithm is not open God's perspective. Therefore, when searching, often seem blind to traverse all possible states of all, this kind of search we collectively blind search.

Heuristic search, by definition, in fact, blind to the computer a little inspiration, a little wisdom to guide the use of these computers reduce the search range, dramatically reducing search complexity. Imagine the BFS process, a certain state at a certain stage the probability of positive solutions significantly larger than any other state, then we prefer these states continue to BFS, to achieve the goal of reducing complexity. So how to calculate the probability of it?

We need some heuristic information to the computer. Different heuristic information have different strengths, neither too strong nor weak, not too strong can lead to positive solutions, and weak will lead to the optimization effect is not obvious. They say so much, and it points to the specific.

How heuristic search?

Before A *, A mention must first algorithm, A * is a special case of A.

Here we introduce a function - "valuation function."

Define a function \ (F (n-) = G (n-) + H (n-) \) , calculated using the heuristic information \ (H \) , according to \ (F \) to identify the most current value of the state of the search function promising node expansion. Where \ (n \) is a state, \ (f \) is the valuation function, \ (G \) is \ (n \) has spent overhead (can understand the information used to do nude BFS), \ ( h \) is a heuristic function.

Heuristic function in different circumstances are different calculation methods, which due to circumstances.

In order to better define the A * algorithm, we have introduced a number of functions: \ (f ^ * (the n-), G ^ * (the n-), H ^ * (the n-) \) .

First, we must be clear, the valuation function mentioned above, is a treat nodes expanded, "estimates", is calculated from the heuristic information, and therefore positive solutions from the initial state to a state corresponding to the actual cost of not spending from.

\ (f ^ * (n) = g ^ * (n) + h ^ * (n) \) indicates the elapsed from the start of the search \ (n \) the actual minimum cost state reach the search target, so you can the \ (f (n), g (n), h (n) \) estimates considered with * these functions.

The A * algorithm is defined to ensure \ (h (n) <h ^ * (n) \) of the A * algorithm, which ensures the optimal solution can be obtained.

We start by example

P1379 eight digital problem

Title Description

3 × 3 on the board, the pendulum eight pieces, each piece is marked with a number of 1 to 8. Chessboard leave a space, space is represented by 0. Pieces can be moved around the space blank space. The problem to be solved is: give an initial layout (initial state) and a target layout (in order to make easy the subject, the target state is set 123,804,765), a method to find the minimum number of steps of the movement, an initial transition from a layout to the layout target .


Obviously, this problem can be done with two-way BFS (source state and the state of the same midpoint mode), and in fact naked BFS this problem could go. . .

But since it is talking about A *, A * will discuss how to do it (wow, there is a solution to a problem I found a giant school guys IDA * QWQ).

In order to make \ (h \) function must be better than (\ h ^ * (n) ) \ small, we consider the structure of such a function. In the initial state, \ (H ^ * (n-) \) is clearly the location of the mobile to the number of all the number of steps required position of the target state. We can assume \ (h (n) \) of \ (n-\) the counted number is not in the target position state. Because obviously, these are no longer the target position by at least one mobile number in order to reach the target position. This is a viable option.

Paste the code:

Used a map to remove duplicate state, in fact, matrix structure inside just overloaded ye do, anyway loaded into the map on the line.

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
using namespace std;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct matrix{
    int a[5][5];
    bool operator<(matrix x) const{
        for(int i=1;i<=3;++i)
            for(int j=1;j<=3;++j)
                if(x.a[i][j]!=a[i][j]) return x.a[i][j]<a[i][j];
        return 0;
    }
}st,f;
inline int h(matrix a)
{
    int tmp=0;
    for(int i=1;i<=3;++i)
        for(int j=1;j<=3;++j)
            if(a.a[i][j]!=st.a[i][j]) tmp++;
    return tmp;
}
struct node{
    matrix a;
    int step;
    bool operator<(node x) const{
        return x.step+h(x.a)<step+h(a);
    }
    node(){};
    node(matrix _a,int _step){a=_a,step=_step;}
};
priority_queue<node> q;
map<matrix,bool> mp;
int main()
{
    st.a[1][1]=1,st.a[1][2]=2,st.a[1][3]=3;
    st.a[2][1]=8,st.a[2][2]=0,st.a[2][3]=4;
    st.a[3][1]=7,st.a[3][2]=6,st.a[3][3]=5;
    char c;
    for(int i=1;i<=3;++i)
        for(int j=1;j<=3;++j){
            scanf("%c",&c);
            f.a[i][j]=c-'0';
        }
    q.push(node(f,0));
    while(q.size()){
        node x=q.top();q.pop();
        if(!h(x.a)){
            printf("%d\n",x.step);
            return 0;
        }
        if(mp[x.a]) continue;
        mp[x.a]=1;
        int nx,ny;
        for(int i=1;i<=3;++i)
            for(int j=1;j<=3;++j)
                if(!x.a.a[i][j]) nx=i,ny=j;
        for(int i=0;i<4;++i){
            int xx=nx+dir[i][0],yy=ny+dir[i][1];
            if(xx>=1&&xx<=3&&yy>=1&&yy<=3){
                swap(x.a.a[xx][yy],x.a.a[nx][ny]);
                q.push(node(x.a,x.step+1));
                swap(x.a.a[xx][yy],x.a.a[nx][ny]);
            }
        }
    }
    return 0;
}

If you want to add ID, then faster, do not speak in detail here, with the average IDBFS specific approach is the same.


P2324 [SCOI2005] chivalry

This question is exactly the same as with the above, no difference, slightly changed the code just fine.

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define ll long long
using namespace std;
int dir[8][2]={{1,2},{-1,2},{2,1},{2,-1},{-2,1},{-2,-1},{1,-2},{-1,-2}};
struct matrix{
    int a[6][6];
    bool operator<(matrix x) const{
        for(int i=1;i<=5;++i)
            for(int j=1;j<=5;++j)
                if(x.a[i][j]!=a[i][j]) return x.a[i][j]<a[i][j];
        return 0;
    }
}st,f;
inline int h(matrix a)
{
    int tmp=0;
    for(int i=1;i<=5;++i)
        for(int j=1;j<=5;++j)
            if(a.a[i][j]!=st.a[i][j]) tmp++;
    return tmp;
}
struct node{
    matrix a;
    int step;
    bool operator<(node x) const{
        return x.step+h(x.a)<step+h(a);
    }
    node(){};
    node(matrix _a,int _step){a=_a,step=_step;}
};
priority_queue<node> q;
map<matrix,bool> mp;
int main()
{
    st.a[1][1]=1,st.a[1][2]=1,st.a[1][3]=1,st.a[1][4]=1,st.a[1][5]=1;
    st.a[2][1]=0,st.a[2][2]=1,st.a[2][3]=1,st.a[2][4]=1,st.a[2][5]=1;
    st.a[3][1]=0,st.a[3][2]=0,st.a[3][3]=-1,st.a[3][4]=1,st.a[3][5]=1;
    st.a[4][1]=0,st.a[4][2]=0,st.a[4][3]=0,st.a[4][4]=0,st.a[4][5]=1;
    st.a[5][1]=0,st.a[5][2]=0,st.a[5][3]=0,st.a[5][4]=0,st.a[5][5]=0;
    int T;
    scanf("%d",&T);
    while(T--){
        mp.clear();
        while(q.size()) q.pop();
        char c;
        for(int i=1;i<=5;++i)
            for(int j=1;j<=5;++j){
                scanf(" %c",&c);
                if(c=='*') f.a[i][j]=-1;
                else f.a[i][j]=c-'0';
            }
        bool flag=0;
        q.push(node(f,0));
        while(q.size()){
            node x=q.top();q.pop();
            if(flag) continue;
            if(x.step>15){
                printf("-1\n");
                flag=1;
            }
            if(!h(x.a)&&!flag){
                printf("%d\n",x.step);
                flag=1;
            }
            if(mp[x.a]) continue;
            mp[x.a]=1;
            int nx,ny;
            for(int i=1;i<=5;++i)
                for(int j=1;j<=5;++j)
                    if(x.a.a[i][j]==-1) nx=i,ny=j;
            for(int i=0;i<8;++i){
                int xx=nx+dir[i][0],yy=ny+dir[i][1];
                if(xx>=1&&xx<=5&&yy>=1&&yy<=5){
                    swap(x.a.a[xx][yy],x.a.a[nx][ny]);
                    q.push(node(x.a,x.step+1));
                    swap(x.a.a[xx][yy],x.a.a[nx][ny]);
                }
            }
        }
    }
    return 0;
}

It is to run more slowly.

Guess you like

Origin www.cnblogs.com/DarkValkyrie/p/11298282.html