図探索のA*アルゴリズム、深さ優先探索と広さ優先探索


A*アルゴリズムの概要:F=G+H
ルートノードのG,H,Fを初期化する.
ルートノードはopenテーブルに追加されます.
while(openテーブルは空ではありません)
{
Openテーブルから評価関数の最小ノードを現在のノードPとして取り出す//ここでopenテーブルの要素数を1つ減らします.
if(Pがターゲットノード)
Pを返します.
Pはcloseテーブルに参加する.
for(Pの各子供ノードchild)
    {
childがcloseテーブルにあるかどうかを判断する.
if(close)
            continue;
        else
        {
childのG代価を計算する;//すなわち、発生した実際の代価
childがopenテーブルにあるかどうかを判断する.
if(openテーブル)
            {
if(childのG代価                {
Openテーブルのchildの親ノードをPに設定します.
Openテーブルのこのchildの評価関数G,H,Fを更新する.
                }
            }else
            {
childの親ノードをPに設定します.
childの評価関数G,H,Fを計算する.
childはopenテーブルに追加されます.
            }
        }
    }
    return false;
}
印刷パスは、親ノードに沿って一歩一歩遡る方法です.
/*
	*           、               A*  。
	*       ROWS*COLS     ,1      ,0     ,    2          。
	*      ,             ,      ,        。
	*                 ,    1         ,   1        。
	*A*          ,                    。
	*    F(x)=G(x)+H(x),G(x)                ,H(x)                。
	*    A*  ,                 
	*/
#include <stdio.h>
#include <windows.h>
#include <math.h>

#define ROWS 22
#define COLS 22
#define UP 0
#define RIGHT 1
#define DOWN 2
#define LEFT 3

int maze[ROWS][COLS]=
	{
		{ 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 2, 1, 1, 1,-1,-1,-1, 1, 1, 0, 0, 1},
		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
		{-1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1},
		{-1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,-1},
		{-1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,-1},
		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1},
		{ 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0},
		{0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,1,0,0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,0,0,1},
		{0,0,0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1},
		{0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,1,0,0},
		{1,0,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,1,1,1,0,0},
		{2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
		{1,0,1,1,0,1,0,1,1,1,0,0,0,0,1,0,0,1,1,0,0,1},
		{0,0,1,1,0,1,0,1,0,1,0,0,1,0,1,1,0,1,1,0,0,1},
		{0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,1,0,1,0,1,0,1,0,1,0,0,1,1,0,1,1,0,0,1},
		{-1,0,1,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,1,0,0,-1},
		{-1,0,0,1,0,1,0,1,0,1,0,1,1,0,1,0,0,1,1,0,0,-1},
		{-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1},
		{1,1,1,0,0,1,1,0,0,1,1,1,1,2,0,1,1,0,1,1,0,1},
	};
int maze_copy[ROWS][COLS]={0};

typedef struct{
	int i;
	int j;
	int direction;
	int number;
	int G;
	int H;
	//int F;
	int pre;
}node;
node path[ROWS*COLS]={0};

void print_maze(int temp[ROWS][COLS])//     
{
	for(int i=0;i<ROWS;i++)
	{
		for(int j=0;j<COLS;j++)
		{
			printf("%3d",temp[i][j]);
		}
		printf("
"); } printf("
"); } void print_path(int maze[ROWS][COLS],node path[],int n)// { for(int i=0;i<n;i++) { printf("\t(%d,%d)\t%d
",path[i].i,path[i].j,maze[path[i].i][path[i].j]); } } int DepthFirstSearch(int in_i,int in_j)// , { memcpy(maze_copy,maze,sizeof(maze)); path[0].i=in_i; path[0].j=in_j; path[0].direction=UP; int p=0; while(p>=0 && p<ROWS*COLS) { if(maze_copy[path[p].i][path[p].j]==2 && p>0) { printf("Found the path: !!!!!!!!!!!!!!!!!
"); break; } maze_copy[path[p].i][path[p].j]=3; if(path[p].direction==UP) { if(path[p].i==0) { path[p].direction=RIGHT;//UP-->RIGHT continue; } if(maze_copy[path[p].i-1][path[p].j]==0 || maze_copy[path[p].i-1][path[p].j]==2) { p++; path[p].i=path[p-1].i-1; path[p].j=path[p-1].j; path[p].direction=UP; } else { path[p].direction=RIGHT;//UP-->RIGHT } } else if(path[p].direction==RIGHT) { if(path[p].j==COLS-1) { path[p].direction=DOWN;//RIGHT-->DOWN continue; } if(maze_copy[path[p].i][path[p].j+1]==0 || maze_copy[path[p].i][path[p].j+1]==2) { p++; path[p].i=path[p-1].i; path[p].j=path[p-1].j+1; path[p].direction=UP; } else { path[p].direction=DOWN;//RIGHT-->DOWN } } else if(path[p].direction==DOWN) { if(path[p].i==ROWS-1) { path[p].direction=LEFT;//DOWN-->LEFT continue; } if(maze_copy[path[p].i+1][path[p].j]==0 || maze_copy[path[p].i+1][path[p].j]==2) { p++; path[p].i=path[p-1].i+1; path[p].j=path[p-1].j; path[p].direction=UP; } else { path[p].direction=LEFT;//DOWN-->LEFT } }else //path[p].direction==LEFT { if(path[p].j==0) { p--; //Back continue; } if(maze_copy[path[p].i][path[p].j-1]==0 || maze_copy[path[p].i][path[p].j-1]==2) { p++; path[p].i=path[p-1].i; path[p].j=path[p-1].j-1; path[p].direction=UP; } else { p--; //Back } } } return p+1; } node open[ROWS*COLS]; node close[ROWS*COLS]; void clear(node temp[ROWS*COLS]) { for(int i=0;i<ROWS*COLS;i++) { temp[i].i=0; temp[i].j=0; temp[i].direction=0; temp[i].G=0; temp[i].H=0; temp[i].number=0; temp[i].pre=0; } } // , , -1 int check1(node *close1,int length,int i,int j) { for(int k=length-1;k>=0;k--) { if(close1[k].i==i && close1[k].j==j) return close1[k].number; } return -1; } // , int BreadthFirstSearch() { open[0].i=12; open[0].j=0; open[0].number=0; int length_open=0; int length_open2=1; int length_close=0; int check_in=-1; int number=10; while(length_open<ROWS*COLS) { node temp=open[length_open];// open length_open++; // int temp_i=0; int temp_j=0; for(int k=0;k<4;k++) { temp_i=temp.i; temp_j=temp.j; if(k==0)// { if(temp.i<=0)continue; temp_i=temp.i-1; } else if(k==1) { if(temp.i>=ROWS-1)continue; temp_i=temp.i+1; } else if(k==2) { if(temp.j<=0)continue; temp_j=temp.j-1; }else { if(temp.j>=COLS-1)continue; temp_j=temp.j+1; } check_in=check1(close,length_close,temp_i,temp_j);// close if(check_in>=0)// close { if(maze[temp.i][temp.j]==maze[temp_i][temp_j]) temp.number=check_in;// , } else// close { if(check1(open,length_open2,temp_i,temp_j)<0)// open , open { open[length_open2].i=temp_i; open[length_open2++].j=temp_j; } } } if(temp.number==0 && maze[temp.i][temp.j]==1) temp.number=++number; close[length_close++]=temp; } for(int i=0;i<length_close;i++) { if(close[i].number>0) maze_copy[close[i].i][close[i].j]=close[i].number; } printf("\tThe numbers of building is:%d
",number); print_maze(maze_copy);// printf("
"); return number; } // , -1, 。 int check(node* temp,int length,int i,int j) { for(int k=length;k>=0;k--) if(temp[k].i==i && temp[k].j==j) return k; return -1; } // , OPEN node choose_min(node *open,int length) { int f=open[0].G+open[0].H; int min=0; for(int i=0;i<length;i++) { if(f>open[i].G+open[i].H) { f=open[i].G+open[i].H; min=i; } } node temp=open[min]; for(int i=min;i<length-1;i++) open[i]=open[i+1]; return temp; } // int printPath_A(int p) { int length=0; while(p>=0) { printf("\t(%d,%d),%d
",close[p].i,close[p].j,maze_copy[close[p].i][close[p].j]); p=close[p].pre; length++; } return length; } //A* , node aStar(int i,int j,int goal_i,int goal_j,int goal) { open[0].i=i; open[0].j=j; open[0].G=0; open[0].H=abs(goal_i-i)+abs(goal_j-j); open[0].pre=-1; int length_open=1; int length_close=0; int check_in=-1; node temp; while(length_open>0 && length_open<ROWS*COLS-1)// OPEN { // OPEN temp=choose_min(open,length_open); //printf("\t(%d,%d),\t%d
",temp.i,temp.j,maze[temp.i][temp.j]); //if((temp.i==goal_i && temp.j==goal_j) || maze_copy[temp.i][temp.j]==goal) if(maze_copy[temp.i][temp.j]==goal) return temp; close[length_close++]=temp;// CLOSE length_open--;// open // , 。 int temp_i=0; int temp_j=0; for(int k=0;k<4;k++) { temp_i=temp.i; temp_j=temp.j; if(k==0) { if(temp.i<=0)continue; temp_i=temp.i-1; } else if(k==1) { if(temp.i>=ROWS-1)continue; temp_i=temp.i+1; } else if(k==2) { if(temp.j<=0)continue; temp_j=temp.j-1; }else { if(temp.j>=COLS-1)continue; temp_j=temp.j+1; } if(maze[temp_i][temp_j]==0 || maze[temp_i][temp_j]==2 ||maze_copy[temp_i][temp_j]==goal) {// // CLOSE check_in=check(close,length_close,temp_i,temp_j); if(check_in<0)// CLOSE { int g=temp.G+1; // OPEN check_in=check(open,length_open,temp_i,temp_j); if(check_in==-1)// OPEN { open[length_open].i=temp_i; open[length_open].j=temp_j; open[length_open].pre=length_close-1; open[length_open].G=g; open[length_open++].H=abs(temp_i-goal_i)+abs(temp_j-goal_j); }else if(g<open[check_in].G)// , 。 { open[check_in].pre=length_close-1; open[check_in].G=g; open[check_in].H=abs(temp_i-goal_i)+abs(temp_j-goal_j); } } } } } temp.pre=-1; return temp; } int LocateBuilding(int number,int *loc_i,int *loc_j)// { for(int i=0;i<ROWS;i++) { for(int j=0;j<COLS;j++) { if(maze_copy[i][j]==number) { *loc_i=i; *loc_j=j; return 1; } } } return 0; } void ShortestPathBetweenTwoBuildings(int NO1,int NO2)// NO1 NO2 { //int p=0; int length=0; int loc1_i,loc1_j,loc2_i,loc2_j; LocateBuilding(NO1,&loc1_i,&loc1_j); LocateBuilding(NO2,&loc2_i,&loc2_j); node p=aStar(loc1_i,loc1_j,loc2_i,loc2_j,maze_copy[loc2_i][loc2_j]);//A* if(p.pre!=-1) { clear(open); clear(close); p=aStar(p.i,p.j,loc1_i,loc1_j,maze_copy[loc1_i][loc1_j]);// , 。 printf("
A* Search:
"); printf("The path of building NO%d to NO%d is:
",NO1,NO2); printf("\t(%d,%d),%d
",p.i,p.j,maze_copy[p.i][p.j]);// length=printPath_A(p.pre);// printf("\tThe path number is:%d
",length+1); } clear(open); clear(close); } void ShortestPathForEachPairBuilding(int number)// { for(int i=11;i<number;i++) { for(int j=i+1;j<=number;j++) { ShortestPathBetweenTwoBuildings(j,i);// i j } } } void main(int argc,char *argv[]) { printf("Maze Map:
"); print_maze(maze);// ( ) // printf("*****************************************************************************

"); int length=DepthFirstSearch(12,0);// , if(length>0 && length<ROWS*COLS) { printf("Depth First Search:
"); print_path(maze,path,length); printf("\tThe path number is:%d

",length); }else{ printf("Can't find
"); } memcpy(maze_copy,maze,ROWS*COLS*sizeof(int)); // printf("*****************************************************************************

"); printf("Seting numbers to every buildings:
"); int number=BreadthFirstSearch();// , 。 clear(open); clear(close); // printf("*****************************************************************************

"); //ShortestPathForEachPairBuilding(number);// A* , // printf("*****************************************************************************

"); while(1) { int NO1,NO2; printf("
Please input the Number of the Start and End Building,The Number shold between 11 and %d
",number); printf("If you input 0,it will close!!!

"); printf("The Start Building NO is:"); scanf_s("%d",&NO1); while(NO1<11 || NO1>number) { if(NO1==0) return; printf("The Start Building NO is:"); scanf_s("%d",&NO1); } printf("The End Building NO is:"); scanf_s("%d",&NO2); while(NO2<11 || NO2>number) { if(NO1==0) return; printf("The End Building NO is:"); scanf_s("%d",&NO2); } ShortestPathBetweenTwoBuildings(NO1,NO2);// NO1 NO2 printf("*****************************************************************************

"); } }