搜索与回溯算法(骗分算法)

本文介绍了搜索与回溯算法的基本概念,提供了一个搜索回溯法的通用框架,并通过实例,如素数环和八皇后问题,详细展示了如何使用该算法解决问题。算法通过递归选择可能的路径,遇到无效情况时进行回溯,直至找到解决方案。
摘要由CSDN通过智能技术生成

一.什么是搜索与回溯算法

搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解。回溯是搜索算法中的一种控制策略。它的基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。

二.搜索回溯法算法框架

 1.

int search(int k){
    for(int i=1;i<=算符种数;i++){
        if(满足条件){
            保存结果
            if(到目的地){
                输出解
            }else{
                search(k+1);
                恢复:保存结果之前的状态(回溯一步)
            }
        }
    }
}

2.

int search(int k){
    if(到目的地){
            输出解
    }else{
        for(int i=1;i<=算符种数;i++){
            if(满足条件){
                保存结果
                search(k+1);
                恢复:保存结果之前的状态(回溯一步)
            }
        }
    }
}

三.例题

题目一

素数环:将1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。

算法分析

非常明显,这是一道回溯的题目。从1开始,每个空位有20种可能,只要填进去的数合法:与前面的数不相同;与左边相邻的数的和是一个素数。第20个数还要判断和第1个数的和是否素数。

算法流程

(1)数据初始化;(2)递归填数:判断第i个数填入是否合法

①如果合法:填数;判断是否到达目标(20个已填完):是打印结果;不是:递归填下一个

②如果不合法:选择下一种可能

代码

#include<bits/stdc++.h>
using namespace std;
bool b[21];
int total=0,a[21];
bool zhi(int n,int m){
	int ji=n+m;
	if(ji==0||ji==1){
		return false;
	}
	for(long long i=2;i*i<=ji;i++){
		if(ji%i==0){
			return false;
		}
	}
	return true;
}
int print(){
	total++;
	cout << "<" << total << ">";
	for(int i=1;i<=20;i++){
		cout << a[i] << " ";
	}
	cout << endl;
}
int search(int t){
	for(int i=1;i<=20;i++){
		if(zhi(a[t-1],i)&&(!b[i])){
			a[t]=i;
			b[i]=1;
			if(t==20){
				if(zhi(a[20],a[1])){
					print();
				}else{
					search(t+1);
				}
				b[i]=0;
			}
		}
	}
}
int main(){
	search(1);
	cout << total << endl;
	return 0;
}

题目二

在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。

无输入

按给定顺序和格式输出所有八皇后问题的解(见样例)。

输出样例

No. 1
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 1 0 0 0 0 0 
No. 2
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 1 0 0 0 0 0 

算法分析

放置第i个(行)皇后的算法为:

int search(int i){
    for(第i个皇后的位置j=1;j<=8;j++){//在本行的8列中去试
        if(本行本列允许放置皇后){
            放置第i个皇后;
            对放置皇后的位置进行标记;
            if(i==8){//已经放完皇后
                输出
            }else{
                search(i+1);//放置第i+1个皇后
                对放置皇后的位置释放标记,尝试下一个位置是否可行;
            }
        }
    }
}

代码

#include<bits/stdc++.h>
using namespace std;
bool d[17],b[9],c[17];
int sum=0,a[9];
int print(){
	sum++;
	cout << "sum=" << sum << endl;
	for(int k=1;k<=8;k++){
		cout << a[k] << " ";
	}
	cout << endl;
}
int search(int i){
	for(int j=1;j<=8;j++){
		if((!b[j])&&(!c[i+j])&&(!d[i-j+7])){
			a[i]=j;
			b[j]=1;
			c[i+j]=1;
			d[i-j+7];//防止数组下标是负数
			if(i==8){
				print();
			}else{
				search(i+1);
				b[j]=0;
				c[i+j]=0;
				d[i-j+7]=0;
			}
		}
	}
}
int main(){
	search(1);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值