这两天学习了一下回溯算法,做一下总结。
算法思想:回溯算法可以看作是蛮力法的升级版,它从解决问题每一步的所有可能选项里系统的选择出一个可行的解决方案。可以形象的用树状结构表示。在某一步有n个可能的选项,那么这一步就可以看成树状结构的一个节点,每个选项看成树中节点连接线,经过这些连接线到达该节点的n个子节点。树的叶子节点对应终结状态。如果找到满足约束条件的状态就找到了一个可行方案。
同样,如果不满足条件则说明该方案不行,此时就退回上一步,再尝试其他选择。直到找到满足的选项,或者所有节点的所有选项都已遍历仍未满足时无解。
总结一下就是:
1.遍历找到满足条件的第一个节点
2.从此节点开始进行递归,若它的子节点、孙节点....,都满足相应的条件则证明找到了合适的解法。若在某一步不满足则退回上一步继续查找。直到所有情况都找完,或者找到合适解法。
经典例题:N皇后问题
剑指offer第12题(矩阵中的路径)等
N皇后问题会单独写一篇,这里就用矩阵中的路径作为示例:
1.题目描述
2.测试用例
3.代码:
bool hasPath(char **board,int rows,int cols,int row,int col,int *length,char *word,char *visit)
{
if(word[*length]=='\0')
return true;
bool haspath=false;
if(col>=0&&col<cols&&row>=0&&row<rows&&board[row][col]==word[*length]&& visit[row*cols+col]==false)
{
(*length)++;
visit[row*cols+col]=true;
haspath=hasPath(board,rows,cols,row+1,col,length,word,visit)||
hasPath(board,rows,cols,row-1,col,length,word,visit)||
hasPath(board,rows,cols,row,col+1,length,word,visit)||
hasPath(board,rows,cols,row,col-1,length,word,visit);
if(haspath==false)
{
visit[row*cols+col]=false;
(*length)--;
}
}
return haspath;
}
bool exist(char** board, int boardSize, int* boardColSize, char* word) {
if(board==NULL||word==NULL||board==0||boardColSize==0)
return false;
int m=boardSize;
int n=boardColSize[0];
int length=0;
bool* visit=malloc(sizeof(bool)*m*n);
memset(visit,0,m*n);
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(hasPath(board,m,n,i,j,&length,word,visit)==true)
{
return true;
}
}
}
return false;
}
注:水平有限,若有差错还望指出,感激不尽。