*検索アルゴリズムの魔法

*

*また、最高のグラフ探索アルゴリズムとして知られているヒューリスティック検索アルゴリズム、です。

ヒューリスティック検索とは何ですか?

我々はすべて知っているように、検索アルゴリズムの時にコンピュータが開かれ、神の視点ではありません。検索するときにそのため、多くの場合、検索のこのような私たちをまとめてブラインドの検索、すべてのすべての可能な状態を横断する盲目のようです。

ヒューリスティック検索は、定義により、実際には、これらのコンピュータの使用を導くために少しのインスピレーション、少し知恵コンピュータにブラインドが劇的に検索の複雑さを軽減、検索範囲を縮小。BFSプロセス、特定の段階他のどの州よりも有意に大きい正のソリューションの確率で特定の状態を想像してみて、それから私達は、これらの状態は、複雑さを削減するという目標を達成するために、BFSに進み好みます。だから、どのようにそれの確率を計算するには?

私たちは、コンピュータに、いくつかのヒューリスティックな情報を必要としています。異なるヒューリスティック情報ポジティブソリューションにつながることができ、かつ弱いが、効果が明らかにされていません最適化につながる強すぎる、どちらも強すぎず、弱いない異なる強みを持っています。彼らは、そんなに言う、それが特定指します。

どのようにヒューリスティック検索?

*前に、言及は、*はAの特殊なケース最初のアルゴリズムである必要があります

ここでは、機能を紹介 - 「評価関数を。」

関数定義\(F(N)= G(N)+ H(N)\)ヒューリスティック情報使用して算出、\(H \)をによると、\(F \)検索機能の状態の最新の値を識別するために有望なノード展開。ここで\(N \)の状態であり、\(Fの\)は評価関数で、\(G \)がされている\(N \) 、(ヌードBFSを実行するために使用される情報を理解することができる)オーバーヘッド費やし\ました(時間\)はヒューリスティック関数です。

異なる状況におけるヒューリスティック関数は事情に異なる計算方法です。

より良好なA *アルゴリズムを定義するために、我々は多くの機能を導入した:\(F ^ *(N)、G ^ *(N)、H ^ *(N)\)

まず、我々は明確にする必要があり、上記の評価関数は、したがって、治療ヒューリスティック情報から計算され、「見積もり」展開されたノード、およびからの支出ではないの実費に相当する状態に初期状態から正のソリューションです。

\(* ^ F(N) = G ^ *(N)+ H ^ *(N)\) 検索の開始からの経過を示している\(N \)実際の最小コスト状態あなたができるように、検索対象に到達\(F(N)、G (n)は、H(N)\) これらの関数*と考え推定。

A *アルゴリズムを確実にするために定義されている\(H(N)<H ^ *(N)\) 最適解が得られることを保証A *アルゴリズムのを。

ここでは、例によって開始します

P1379 8つのデジタル問題

タイトル説明

ボード上の3×3、振り子8個は、各ピースは1〜8の番号が付いています。チェス盤のスペースを残して、スペースが0で表現されます。作品はスペース空白の周りに移動することができます。解決すべき問題は、初期レイアウト(初期状態)とターゲット・レイアウト(やすい被験体を作るために、目標状態が123804765に設定されている)、移動のステップの最小数を見つけるための方法、レイアウトターゲットのレイアウトから初期転移を与えます。


明らかに、この問題は、双方向BFS(ソース状態と同じ中間モードの状態)で行うことができ、かつ実際に裸のBFSにこの問題は行くことができます。

しかし、それは*について話しているので、*はそれを行う方法について説明します(うわー、私は巨大な学校のみんなIDA * QWQを発見した問題の解決策があります)。

作るために\(時間\)機能がより良くなければなりません(\ H ^ *(n)が \) 小さな、我々はそのような機能の構造を考えます。初期状態では、\(H ^ *(N)\)明確に目標状態の位置に必要なステップの全ての数の数にモバイルの位置です。我々は仮定することができる(H(N)\)\\(N- \)カウント数が目標位置状態ではありません。明らかに、これらはもはや目標位置に到達するために少なくとも1つの携帯電話番号による目標位置ではないので。これは実行可能な選択肢です。

コードを貼り付けます。

重複した状態を削除するにはマップを使用し、実際には、単にオーバーロードされたあなたがた内部のマトリックス構造は、とにかくライン上のマップにロードされます。

#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;
}

あなたがIDを追加したい場合は、より速く、平均IDBFS特定のアプローチで、ここでは詳細に話すことはありません同じです。


P2324 [SCOI2005]騎士道

この質問は、上記のようにまったく同じです、何の違いは、少しうまくコードを変更しません。

#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;
}

これは、もっとゆっくり実行することです。

おすすめ

転載: www.cnblogs.com/DarkValkyrie/p/11298282.html