1. 程式人生 > >廣度優先搜尋解決八數碼問題

廣度優先搜尋解決八數碼問題

#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
using namespace std;
#define N 9
int jc[N+1]={1,1,2,6,24,120,720,5040,40320,362880};//0-9的階乘
typedef struct data
{
    int arr[N];//格局
    int hash;//儲存某一格局的雜湊
    int pos;//0當前位置
    int step;//記錄步數
}Node;

int dir[4][2]={
    {0,1},
    {1,0},
    {0,-1},
    {-1,0}
};

/**
*  康託展開
*/
int cantor(int arr[N])
{
    int i,j;
    int sum=0;
    for( i=0;i<N;i++)
    {
        int nmin=0;
        for(j=i+1;j<N;j++)
        {
            if(arr[i]>arr[j])
                nmin++;
        }
        sum+=(nmin*jc[N-i-1]);

    }

    return sum;
}

/**
*資料交換
*/
void swap(int *arr,int i,int j)
{
    int t=arr[i];
    arr[i]=arr[j];
    arr[j]=t;
}

/**
* 列印陣列,測試用
*/
void printArray(int * arr)
{
    int i,j;
    for (i=0;i<N;i++)
    {
        if(i%3==0)
            cout<<"\n";
        cout<<arr[i]<<" ";
    }
    cout<<endl;
}
/**
* 複製陣列
*/
void copyArray(int src[N],int target[N])
{
    int i;
    for(i=0;i<N;i++)
    {
        target[i]=src[i];
    }

}


/**
* 廣搜
*/
int bfs(int arr[N],int sHash,int tHash)
{
    if(sHash==tHash)
        return 0;
    int i,j;
    queue<Node> q;
    set<int> setHash;
    Node now,next;
    copyArray(arr,now.arr);
    int pos=0;
    for (i=0;i<N;i++)
    {
        if(arr[i]==0)
            break;
        pos++;
    }
    now.hash=sHash;
    now.step=0;
    next.step=0;
    now.pos=pos;
    q.push(now);
    setHash.insert(now.hash);

    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for (i=0;i<4;i++)
        {
            int offsetX=0,offsetY=0;
            offsetX=(now.pos%3+dir[i][0]);
            offsetY=(now.pos/3+dir[i][1]);

            if(offsetX>=0&&offsetX<3&&offsetY<3&&offsetY>=0)
            {
                copyArray(now.arr,next.arr);//每次換方向,就複製
                next.step=now.step;

                next.step++;
                swap(next.arr,now.pos,offsetY*3+offsetX);

                next.hash=cantor(next.arr);
                next.pos=(offsetY*3+offsetX);
                int begin=setHash.size();
                setHash.insert(next.hash);
                int end=setHash.size();

                if(next.hash==tHash){

                    return next.step;
                }

                if(end>begin)
                {

                    q.push(next);
                }

            }
        }

    }
    return -1;
}

/**
*求逆序數
*/
int inversion(int arr[N])
{
    int sum=0;
    for(int i=0;i<N;++i)
    {
        for(int j=i+1;j<N;++j)
        {
            if(arr[j]<arr[i]&&arr[j]!=0)//不與0比較
            {
                sum++;
            }
        }
    }

    return sum;

}
int main(int argc, char **argv)
{
    int i,j;
    string s="123456780";
    string t="123456078";
    int is[N],it[N];//源int陣列和目標int陣列
    for (i=0;i<9;i++)
    {
        if (s.at(i)>='0'&&s.at(i)<='8')
        {
            is[i]=s.at(i)-'0';
        }else
        {
            is[i]=0;
        }
        if (t.at(i)>='0'&&t.at(i)<='8')
        {
            it[i]=t.at(i)-'0';
        }else
        {
            it[i]=0;
        }
    }
    int sHash,tHash;//源雜湊和目標雜湊

    sHash=cantor(is);
    tHash=cantor(it);
    int inver1=inversion(is);//求初始格局的逆序數
    int inver2=inversion(it);//求目標格局的逆序數
    if((inver1+inver2)%2==0)
    {
        int step=bfs(is,sHash,tHash);
        cout<<step<<endl;
    }
    else
    {
        cout<<"無法從初始狀態到達目標狀態"<<endl;
    }

    return 0;
}


相關推薦

廣度優先搜尋解決數碼問題

#include <iostream> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include &

廣度優先搜尋(8數碼問題)

#include <iostream>#include <vector>#include <limits>#include <string>#include<set>       #include<queue&

廣度優先搜尋-數碼問題

演算法簡介:廣度優先搜尋 問題 給定一個一幅圖和一個起點s,回答“從s到給定的頂點v是否存在一條路徑?如果有,找出其中最短的那條(所含邊數最少)。“ 思路 邊數最少,很自然想到從從經過1條邊能到達的節點有哪些?然後經過這些邊再到達的節點有哪些?這

圖演算法_普通廣度優先搜尋(BFS)解數碼問題_C語言

Copyright (C)2009 Chris Xue. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Docume

廣度優先搜尋--演算法圖解--書中部分"錯誤"解決記錄

在<圖解演算法>的第六章 廣度優先搜尋中,6.5進行演算法實現時,報如下錯誤: UnboundLocalError: local variable 'search_queue' referenced before assignment   原始碼(書本是python2.

資訊學奧賽一本通(C++版) 第二部分 基礎演算法 第廣度優先搜尋

//1329 【例8.2】細胞//編寫過程中,發現輸入資料用整數無法讀取,要採用字串形式//核心思路,將非零數字字元改成0字元 //將程式碼修改,提交AC #include <stdio.h>int n,m,next[][2]={{1,0},{-1,0},{0,1},{0,-1}};char a[

廣度優先搜尋——經典的8數碼問題

話不多說,直接貼程式碼吧~ //廣度搜索-8數碼問題 #include <iostream> #include <cstring> using namespace std; const int Max = 8; const int All =

【轉】A*算法解決數碼問題

nim fir 空格 sin get () explore sed deepcopy from utils import ( PriorityQueue) import copy infinity = float(‘inf‘) def best_first_gr

廣度優先搜尋雙佇列通用程式設計模板

廣度優先搜尋主要用於解決求最短問題,如最短路徑,最少變化步數問題等等,思想是從起點出發,按層遍歷,直到搜尋到目標或者已經搜尋完全部區域。通常利用佇列實現廣度優先搜尋,我這裡使用的雙佇列法,用一個佇列cur表示當前層,next表示由當前層擴充套件的下一層,用雙佇列有個好處是我們只需要定義一個全域性

演算法7-6:圖的遍歷——廣度優先搜尋

http://www.dotcpp.com/oj/problem1703.html 題目描述 廣度優先搜尋遍歷類似於樹的按層次遍歷的過程。其過程為:假設從圖中的某頂點v出發,在訪問了v之後依次訪問v的各個未曾被訪問過的鄰接點,然後分別從這些鄰接點出發依次訪問它們的鄰接點,並使“先被訪問的

佇列的JS實現及廣度優先搜尋(BFS)的實現

佇列是先進先出(FIFO)的資料結構,插入操作叫做入隊,只能新增在佇列的末尾;刪除操作叫做出隊,只能移除第一個元素。在JS中,用陣列可以很簡單的實現佇列。 function Queue () { this.queue = []; } // 增加 Queue.prototype.enQueue = f

廣度優先搜尋(鄰接表)

#include <iostream> #include <cstdio> #include <vector> #include <queue> using namespace std; struct Node{ //to 代表每個節點

利用佇列廣度優先搜尋

//廣度優先搜尋樹,一定要使用佇列,佇列的特性很好用 import java.util.*; public class Guangduyouxiansousuosuanfa1 { public static void main(String args[]){ Scanner

【BFS】層層遞進—廣度優先搜尋

【BFS】層層遞進—廣度優先搜尋 Breadth First Search 啊哈演算法 迷宮中尋找小哈   #include <iostream> #include <stdio.h> #include <stdlib.h> using na

資料結構——圖(4)——廣度優先搜尋(BFS)演算法思想

廣度優先搜尋 儘管深度優先搜尋具有許多重要用途,但該策略也具有不適合某些應用程式的缺點。 深度優先方法的最大問題在於它從其中一個鄰居出發,在它返回該節點或者是訪問其他鄰居之前,它必須訪問完從出發節點開始的整個路徑。 如果我們嘗試在一個大的圖中發現兩個節點之間的最短路徑,則使用深度優先

python 遞迴深度優先搜尋廣度優先搜尋演算法模擬實現

一、遞迴原理小案例分析 (1)# 概述 遞迴:即一個函式呼叫了自身,即實現了遞迴 凡是迴圈能做到的事,遞迴一般都能做到! (2)# 寫遞迴的過程 1、寫出臨界條件2、找出這一次和上一次關係3、假設當前函式已經能用,呼叫自身計算上一次的結果,再求出本次的結果 (3)案例分析:求1+2+3+…+n的數和

鄰接表建立無向圖,廣度優先搜尋遍歷輸出

1 #include<stdio.h> 2 #include<string.h> 3 #include <iostream> 4 #include<algorithm> 5 using namespace std; 6 #defin

深度優先搜尋遍歷與廣度優先搜尋遍歷

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

無向圖鄰接連結串列的廣度優先搜尋

個人認為圖的演算法看起來非常簡潔,但是實現起來需要基礎很紮實。因為經常會涉及多種簡單的資料結構,怎樣把他們恰當的串聯起來,不會報那種,空指標了,型別不匹配,實體型別不符合了等等。 在做無向圖鄰接連結串列廣度優先搜尋的時候,寫的很冒火,想去找別的博主的程式碼借鑑一下,發現大部分,真的是大部分,

搜尋_BFS(廣度優先搜尋)_演算法分析

    為方便討論BFS演算法, 考慮對圖的每個結點設定屬性color表示結點的顏色, color可取WHITE, GRAY, BLACK, 設定屬性d表示對應結點到源結點的最短路徑長度, 設定屬性p, 其中v.p表示存在一條從源結點到結點v的最短路徑且v的前驅為v.p, 下