贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。(来自百度)
其中基于深度优先搜索的算法就是依据当前点找到下一个可能的点,然后对这个点进行深度优先搜索,然后依次递归,当出现条件不满足时,退回来,采用其他的路劲进行搜索,最后肯定能够得到对应的结果。实现的基本过程如下:
/*deepsearch to solve the horse chess problem*/ #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROWS 8 #define COLS 8 int chess[ROWS][COLS]; /*eight directions of x moved*/ const int x_move[] = {-2,-1,1,2,2,1,-1,-2}; /*eight directions of y moved*/ const int y_move[] = {1,2,2,1,-1,-2,-2,-1}; void print_matrix() { int i = 0,j = 0; for (i = 0; i < ROWS; ++ i) { for (j = 0; j < COLS; ++ j) { printf("%d\t",chess[i][j]); } printf("\n\n\n"); } } /*find the next point*/ int nextxy(int *x,int *y,int count) { if(count > 7 && count < 0) return -1; switch(count) { case 0: /*check the conditions*/ if(*x + x_move[0] < ROWS && *x + x_move[0]>= 0 && *y + y_move[0]< COLS && *y + y_move[0]>= 0 && chess[*x + x_move[0]][*y + y_move[0]] == 0) { *x += x_move[0]; *y += y_move[0]; break; } else/*failed*/ return 0; case 1: if(*x + x_move[1] < ROWS && *x + x_move[1]>= 0 && *y + y_move[1]< COLS && *y + y_move[1]>= 0 && chess[*x + x_move[1]][*y + y_move[1]] == 0) { *x += x_move[1]; *y += y_move[1]; break; } else return 0; case 2: if(*x + x_move[2] < ROWS && *x + x_move[2]>= 0 && *y + y_move[2]< COLS && *y + y_move[2]>= 0 && chess[*x + x_move[2]][*y + y_move[2]] == 0) { *x += x_move[2]; *y += y_move[2]; break; } else return 0; case 3: if(*x + x_move[3] < ROWS && *x + x_move[3]>= 0 && *y + y_move[3]< COLS && *y + y_move[3]>= 0 && chess[*x + x_move[3]][*y + y_move[3]] == 0) { *x += x_move[3]; *y += y_move[3]; break; } else return 0; case 4: if(*x + x_move[4] < ROWS && *x + x_move[4]>= 0 && *y + y_move[4]< COLS && *y + y_move[4]>= 0 && chess[*x + x_move[4]][*y + y_move[4]] == 0) { *x += x_move[4]; *y += y_move[4]; break; } else return 0; case 5: if(*x + x_move[5] < ROWS && *x + x_move[5]>= 0 && *y + y_move[5]< COLS && *y + y_move[5]>= 0 && chess[*x + x_move[5]][*y + y_move[5]] == 0) { *x += x_move[5]; *y += y_move[5]; break; } else return 0; case 6: if(*x + x_move[6] < ROWS && *x + x_move[6]>= 0 && *y + y_move[6]< COLS && *y + y_move[6]>= 0 && chess[*x + x_move[6]][*y + y_move[6]] == 0) { *x += x_move[6]; *y += y_move[6]; break; } else return 0; case 7: if(*x + x_move[7] < ROWS && *x + x_move[7]>= 0 && *y + y_move[7]< COLS && *y + y_move[7]>= 0 && chess[*x + x_move[7]][*y + y_move[7]] == 0) { *x += x_move[7]; *y += y_move[7]; break; } else return 0; default: return 0; } return 1; } int deepsearch(int x,int y, int j) { /*save the value x,y*/ int x1 = x, y1 = y; int tag = 0, i = 0; /*save j on chess[x][y]*/ chess[x][y] = j; /*recursion exit condition*/ if(j == COLS*ROWS) { return 1; } /*find the next point in eight directions*/ tag = nextxy(&x1,&y1,i); /*find the nextx,nexty */ while (tag == 0 && i < 7) { i ++; tag = nextxy(&x1,&y1, i); } /*the nextxy be found*/ while(tag) { if(deepsearch(x1,y1,j+1)) return 1; /*if failed, a new finding process */ x1 = x; y1 = y; i ++; tag = nextxy(&x1,&y1,i); while (tag == 0 && i < 7) { i ++; tag = nextxy(&x1,&y1,i); } } /*no direction can find next point*/ if(tag == 0) chess[x][y] = 0; return 0; } void main() { clock_t start = clock(); deepsearch(2,0,1); print_matrix(); int seconds = (clock()-start)/CLOCKS_PER_SEC; printf("\n%d\n",seconds); return; }采用贪婪算法的实现,首先应该设置一定的判断准则,然后根据设定的准则进行选择,在马踏棋盘中设定的准备是选择出路最少(至少为1)的一个方向为准则,能够实现马踏棋盘问题的解决。当然该问题为什么要选择出路最少,我暂时还不是很清楚。基本的实现如下:
点击(此处)折叠或打开
#include <stdio.h> #include <stdlib.h> #include <math.h> #define ROWS 8 #define COLS 8 /*axis i move matrix*/ const int iktmove[8] = {-2,-1,1,2,2,1,-1,-2}; /*axis j move matrix*/ const int jktmove[8] = {1,2,2,1,-1,-2,-2,-1}; int board[ROWS][COLS]; /*inital the matrix*/ void matrix_init(int matrix[][COLS],int rows,int cols) { int i, j; for(i = 0; i < rows ; ++ i) for (j = 0; j < cols ; ++ j) { matrix[i][j] = 0; } } /*print the matrix*/ void print_matrix(int matrix[][COLS],int rows,int cols) { int i,j; for(i = 0; i < rows; ++ i) { for(j = 0; j < cols; ++ j) printf("%d\t",matrix[i][j]); printf("\n\n\n"); } } /*find the index of min non-zeros positive*/ int minindex_in_matrix(int a[],int cols) { int i = 0,index = 0; int min = a[0]; for(i = 0 ; i< cols; ++ i) { if(a[i] >0) { min = a[i]; index = i; break; } } for(i = index + 1; i < cols ; ++ i) { if(a[i] > 0 && min > a[i]) { min = a[i]; index = i; } } if(a[index] > 0) return index; return -1; } int maxindex_in_matrix(int a[],int cols) { int i = 0,index; int max ; for(i = 0 ; i< cols; ++ i) { if(a[i] >0) { max = a[i]; index = i; break; } } for(i = index + 1; i < cols ; ++ i) { if(a[i] > 0 && max < a[i]) { max = a[i]; index = i; } } if(a[index] > 0) return index; return -1; } /**/ void warnsdorff_role(int matrix[][COLS],int rows,int cols,int start_i,int start_j) { int i,npos,m,min,j,nnpos; int nexti[8] = {0,0,0,0,0,0,0,0}; int nextj[8] = {0,0,0,0,0,0,0,0}; int exit[8] = {0,0,0,0,0,0,0,0}; /*steps a*/ matrix_init(matrix,rows,cols); /*steps b*/ matrix[start_i][start_j] = 1; /*steps c*/ for(m = 1; m < 64; ++ m) { /*steps d*/ npos = 0; for(i = 0; i < 8; ++ i) { /*ignore the point which doesn't satisfy the conditions*/ if( start_i + iktmove[i] < 0 || start_i + iktmove[i] >= rows || start_j + jktmove[i] < 0 || start_j + jktmove[i] >= cols || matrix[start_i + iktmove[i]][start_j+jktmove[i]] > 0) { continue; } /*save the point which satisfy the conditions*/ nexti[npos] = start_i + iktmove[i]; nextj[npos] = start_j + jktmove[i]; /*statistics how many point satisfy conditions*/ npos ++; } /*steps e*/ if(npos == 0) { printf("Can not finish the game!!\n,The steps of game can be %d\n",m); goto print; } /*steps e*/ if(npos == 1) { min = 0; goto set_nextpoint; } /*steps f*/ if(npos > 1) { /*calculate the possible way of the next next step */ for(i = 0; i < npos ; ++ i) { nnpos = 0; for(j = 0; j < 8; ++ j) { /*statistics the point which satisfy conditions*/ if( nexti[i] + iktmove[j] >= 0 && nexti[i] + iktmove[j] < rows && nextj[i] + jktmove[j] >= 0 && nextj[i] + jktmove[j] < cols && matrix[nexti[i] + iktmove[j]][nextj[i] + jktmove[j]] == 0) { nnpos ++; } } /*save the numbers of points for next step*/ exit[i] = nnpos; } /*find the proper point*/ if((min = minindex_in_matrix(exit,npos)) >= 0) { goto set_nextpoint; } else /*failed*/ { printf("Can not finish the game!!\n,The steps of game can be %d\n",m); goto print; } } set_nextpoint: /*step g*/ /*set the next start point of game*/ start_i = nexti[min]; start_j = nextj[min]; matrix[start_i][start_j] = m+1; } print: /*step h*/ print_matrix(matrix,rows,cols); } void main() { warnsdorff_role(board,ROWS,COLS,5,1); }实现结果:当采用深度优先搜索算法的过程中发现当棋盘为8X8时,计算速度非常的慢,而当棋盘为5X5以后,计算速度非常的快速。说明算法存在一定的缺陷。而采用贪婪算法实现的速度非常的快,棋盘的大小对算法性能影响较小。
将矩阵改为5X5得到如下的结果:从结果中可以看见两种算法得到的结果存在一定的差异,但是都能解决马踏棋盘问题。
1、深度优先搜索算法:
2、贪婪算法:
