数据结构算法之回溯法求解

26 篇文章 0 订阅
23 篇文章 0 订阅

回溯的基本原理

在问题的解空间中,按深度优先遍历策略,从根节点出发搜索解空间树。算法搜索至解空间
的任意一个节点时,先判断该节点是否包含问题的解。如果确定不包含,跳过对以该节点为根的
子树的搜索,逐层向其祖先节点回溯,否则进入该子树,继续深度优先搜索。
回溯法解问题的所有解时,必须回溯到根节点,且根节点的所有子树都被搜索后才结束。回
溯法解问题的一个解时,只要搜索到问题的一个解就可结束。
回溯的基本步骤

  1. 定义问题的解空间
  2. 确定易于搜索的解空间结构
  3. 以深度优先搜索的策略搜索解空间,并在搜索过程中尽可能避免无效搜索
    请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以
    从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了
    矩阵的某一格,那么该路径不能再次进入该格子。例如在下面的 3×4 的矩阵中包含一条字符串
    “bfce”的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为
    字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
    A B T G
    C F C S
    J D E H
#include<stdio.h>
#include<Windows.h>

//四个参数 传入的字符数组,行,列,搜索的字符串
bool FindChars(const char *marinx,int rows,int cols,const char *str);

//递归的搜索函数 8个参数 传入的字符数组,行,列,搜索到的行,列,搜索字符串,走了多少步,该点是否已经访问
bool hasPath(const char *marinx,int rows,int cols,int row,int col,const char *str,int &Path,bool *visit);



bool FindChars(const char *marinx,int rows,int cols,const char *str){


	//防御性编程
	if(rows<0||cols<0||marinx==nullptr) return false;

	//记录走了多少步,也就是用这个步数来判断str是否已经搜索到
	int PathStep = 0;

	bool *visit = new bool[rows*cols];

	memset(visit,0,rows*cols);

	for(int row=0;row<rows;row++){
		
		for(int col=0;col<cols;col++){
		
			 if(hasPath(marinx,rows,cols,row,col,str,PathStep,visit)) return true;

			}
	
		}

	delete []visit;

	return false;


	}


bool hasPath(const char *marinx,int rows,int cols,int row,int col,const char *str,int &Path,bool *visit){

	//搜索成果条件,到了str的字符串结束符
	if(str[Path]=='\0') return true;

	//进入的条件,首先这个点要在这个数组内,其次这个点没被访问过并且这个点等于这个str[Path]
	
	bool haspath = false;//一个标志位记录有没有路

	if(row<rows&&row>=0&&col>=0&&col<cols&&marinx[row*cols+col]==str[Path]&&visit[row*cols+col]==false){
	//不行的情况

		//此时这个点是没有访问的并且满足条件
		Path++;
		visit[row*cols+col] = true;

		//进入下一个点

		haspath = hasPath(marinx,rows,cols,row+1,col,str,Path,visit)
			||hasPath(marinx,rows,cols,row-1,col,str,Path,visit)
			||hasPath(marinx,rows,cols,row,col+1,str,Path,visit)
			||hasPath(marinx,rows,cols,row,col-1,str,Path,visit);
		
		//这种是
		
		//当结束深度查找的时候要回溯置位
		if(!haspath){
		Path--;
		visit[row*cols+col] = false;
			}
		

		}
	return haspath;

	}

//测试代码
void test(const char *marinx,int rows,int cols,const char *str,bool &isPass){

	isPass =FindChars( marinx, rows, cols, str);

	if(isPass)printf("Successfully find:%s\n",str);
	else printf("hava no find:%s",str);
	
}

int main(void){

	char marinx[]={ 'A','B','T','G'
				   ,'C','F','C','S',
			 	    'J','D','E','B'};
	//char *marinx  ="ABTGCFCSJDEB";
	char *str ="ACJDE";
	bool ret =false;
	test(marinx,3,4,str,ret);

	str ="ABTGSBEDJCFC";
	test(marinx,3,4,str,ret);

	system("pause");
	return 0;
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值