Vijos1360[八數碼問題] 搜索

背景

Yours和zero在研究A*啓發式算法.拿到一道經典的A*問題,但是他們不會做,請你幫他們.

描述

在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有一個空格,空格用0來表示。空格周圍的棋子可以移到空格中。要求解的問題是:給出一種初始佈局(初始狀態)和目標佈局(爲了使題目簡單,設目標狀態爲123804765),找到一種最少步驟的移動方法,實現從初始佈局到目標佈局的轉變。

格式

輸入格式

輸入初試狀態,一行九個數字,空格用0表示

輸出格式

只有一行,該行只有一個數字,表示從初始狀態到目標狀態需要的最少移動次數(測試數據中無特殊無法到達目標狀態數據)

樣例1

樣例輸入1

283104765

樣例輸出1

4


solution:搜索

#include <set>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

int endi[4][4]={0,0,0,0,0,1,2,3,0,8,0,4,0,7,6,5};
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

struct Matrix{
    int m[4][4];
    Matrix(int s[4][4] ){
        for ( int i=1; i<=3; i++ )
            for ( int j=1; j<=3; j++ )
                m[i][j]=s[i][j];
    }
    bool operator<(const Matrix& s) const{
        for ( int i=1; i<=3; i++ )
            for ( int j=1; j<=3; j++ )
                if( m[i][j]!=s.m[i][j] )
                    return m[i][j]<s.m[i][j];
        return 0;
    }
    Matrix(){}
};

struct Point{
    int x, y, h, f, cnt;
    int m[4][4];
    bool operator<(const Point& s) const {
        return f>s.f;
    }
    Point(){}
}sp;

priority_queue<Point> Q;
set<Matrix> S;

bool in(int x, int y){
    return (x>=1 && x<=3 && y>=1 && y<=3 );
}
int bfs(Point po){
    Q.push(po);
    Matrix t1(po.m);
    S.insert(t1);
    int step=-1;
    while( !Q.empty() ){
        Point tmp=Q.top();
        Q.pop();
        Matrix t2(tmp.m);
        if( step!=-1 && tmp.cnt>step ) continue;
        if( tmp.h==0 ) step=tmp.cnt;
        if( tmp.cnt>105 ) return -1;
        for ( int i=0; i<4; i++ ){
            Point tp=tmp;
            tp.x=tmp.x+dx[i], tp.y=tmp.y+dy[i];
            tp.cnt=tmp.cnt+1;
            if( in(tp.x,tp.y) ){
                int cnt=0;
                swap( tp.m[tp.x][tp.y], tp.m[tmp.x][tmp.y] );
                for ( int i=1; i<=3; i++ )
                    for ( int j=1; j<=3; j++ )
                        if( tp.m[i][j]!=endi[i][j] ) cnt++;
                tp.h=cnt;
                tp.f=tp.h+tp.cnt;
                Matrix t3(tp.m);
                if( S.find(t3)==S.end() ){
                    S.insert(t3);
                    Q.push(tp);
                }
            }
        }
    }
    return step;
}
int main(){
    int z=0;
    for ( int i=1; i<=3; i++ )
        for ( int j=1; j<=3; j++ ){
            scanf("%1d", &sp.m[i][j] );
            if( !sp.m[i][j] ) sp.x=i, sp.y=j;
            else if( sp.m[i][j]!=endi[i][j] ) z++;
        }
    sp.h=sp.f=z;
    sp.cnt=0;
    printf("%d", bfs(sp) );
    return 0; 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章