廣度優先演算法查詢路線

VanJames發表於2019-03-19

1表示走不通 0可走通,可看成一張正方形平面迷宮圖,現在需要找出從左上角作為第一個格走到右下角最後一個格的所有路線

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

建模思路

    1.每個方格作為一個物件
    2.每個物件可以用座標表示(x,y)
    3.每個物件可以獲取它相鄰的上下左右四個物件(不存在的也可以表示) 
        左:(x-1,y) 右:(x+1,y)
        上:(x,y-1) 下:(x,y+1)
    4.每個物件都有屬性是否可通或者存在
        status:value==0 and x >= 0 and y >=0 
    5.從第一個點開始走,往上下左右各個方向嘗試走,走到下一個點,
      記錄前面經過的所有點, 繼續往四個方向走,直到找到包含終點所有的路線。
package cuckoo

import (
    "fmt"
    "testing"
)

const SIZE = 5

type point struct {
    x int64   //頂點1 x座標
    y int64   //頂點2 y座標
    union bool //是否聯通
} //x,y座標

var points map[int64]point

func (this *point)status()bool{
    if this.x < 0 || this.y < 0{
        return false
    }
    return true
}

func getPointKey(x,y int64) int64 {
    return x * SIZE + y
}

//上部座標
func (this *point)up()point{
    if this.x > 0{
        //不在第一行
        k := getPointKey(this.x-1,this.y)
        if _,ok := points[k];ok{
            return points[k]
        }
    }
    return point{-1,-1,false}
}

//下部座標
func (this *point)down()point{
    if this.x < 4{
        //不在最後行
        k := getPointKey(this.x+1,this.y)
        if _,ok := points[k];ok{
            return points[k]
        }
    }
    return point{-1,-1,false}
}

//左部座標
func (this *point)left()point{
    if this.y >0{
        //不在第一列
        k := getPointKey(this.x,this.y-1)
        if _,ok := points[k];ok{
            return points[k]
        }
    }
    return point{-1,-1,false}
}

//左部座標
func (this *point)right()point{
    if this.y <4{
        //不在最後一列
        k := getPointKey(this.x,this.y+1)
        if _,ok := points[k];ok{
            return points[k]
        }
    }
    return point{-1,-1,false}
}

//一個點是否是另一個點的相鄰點
func (this *point)hasnext(po point)bool{
    if this.up().x == po.x && this.up().y == po.y{
        return true
    }
    if this.down().x == po.x && this.down().y == po.y{
        return true
    }
    if this.left().x == po.x && this.left().y == po.y{
        return true
    }
    if this.right().x == po.x && this.right().y == po.y{
        return true
    }
    return false
}

type unionpath [][]int64

/**

    1表示走不通 0可通

    0 1 0 0 0
    0 1 0 1 0
    0 0 0 0 0
    0 1 1 1 0
    0 0 0 1 0
 */

var allpath map[int64]unionpath

func TestBFS(t *testing.T){
    //初始化矩陣

    in := [SIZE][SIZE]int64{{0,1,0,0,0},{0,1,0,1,0},{0,0,0,0,0},{0,1,1,1,0},{0,0,0,1,0}}

    //初始化圖形點
    points = make(map[int64]point,0)
    for x:=0;x<SIZE;x++{
        for y:=0;y<SIZE;y++{
            p := point{}
            p.x = int64(x)
            p.y = int64(y)
            p.union = false
            if in[x][y] == 0{
                p.union = true
            }
            points[getPointKey(int64(x),int64(y))] = p
        }
    }

    fmt.Println(len(points),points)
    //找出所有路徑
    allpath = make(map[int64]unionpath,0)
    findPath(int64(0),[]int64{},points[0])
    //將路徑整理出來
    for k:= 0;k<len(allpath);k++{
        for _,v := range allpath[int64(k)]{
            if inarray(0,v) && inarray(24,v){
                fmt.Println("找到完整路徑:",v,"長度:",len(v))
            }
        }
        fmt.Println(allpath[int64(k)],"長度:",len(allpath[int64(k)]))
    }

}

func inarray(address int64,m []int64) bool {
    for _,v := range m{
        if v == address{
            return true
        }
    }
    return false
}

func inpath(po point,pa []int64) bool  {
    for _,k := range pa{
        if getPointKey(po.x,po.y) == k{
            return true
        }
    }

    return false
}

func findPath(level int64,parents []int64,po point){

    if inpath(po,parents){
        return
    }

    if po.status() && po.union {
        //連通的點
        parents = append(parents,getPointKey(po.x, po.y))
        allpath[level] = append(allpath[level],parents)
        //上
        findPath(level+1,parents,po.up())
        //下
        findPath(level+1,parents,po.down())
        //左
        findPath(level+1,parents,po.left())
        //下
        findPath(level+1,parents,po.right())
    }
    return
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章