穷举搜索:回溯与深搜

计算机常用算法大致有两大类,一类叫蛮力算法,一类叫贪心算法,前者常使用的手段就是搜索,对全部解空间进行地毯式搜索,直到找到指定解或最优解。

【建立解空间】
问题的解应该如何描述,如何建立?借助图论的思想,我们可以用图来描述,图的定义为G,由顶点集和边集构成,顶点即实实在在的数 据、对象,而边可以抽象为关系,即顶点间的关系,这种关系不一定非要在数据结构上表现出来,用数据结构的语言来描述,如果关系是一对一,则为线性表,如果 关系是一对多,则为树,如果关系是多对多,则为图,如果完全没有关系,则为集合。但在数据结构中这种关系不一定非要在数据的存储性质上一开始就表现出来, 譬如,你可以用一个数组表示一个线性表,也可以表示完全二叉树,同样也可以用邻接表表示一个图,对于关系的描述不是数据结构本身的描述,而是算法的描述, 正如数据结构是离不开特定的算法一样,不可分开单独而谈。描述了解,那如何建立解空间,即如何对图进行搜索?

【深度优先搜索】
(Depth First Search)是用栈的机制对图的顶点进行深度优先的搜索。简易流程如下:

DFS(V0(起始顶点))
访问V0
for(v=V0的第一个子结点 到 最后一个子结点(边所对的顶点))
如果v未被访问,DFS(v);

搜索过程是先往结点深处搜索,一旦有子结点未访问就向下遍历。这样的方法类似回溯算法,先往下试探,如果不行出退回(回溯)。

【回溯】
回溯的经典例子是8皇后问题。
例:在国际象棋地图上(8×8)放上8个皇后,使任意两个皇后都不在同一行或同一列或同一斜行,找出所有解。
每一个皇后的位置可以认为是一个顶点,而皇后之间不在同一行或同一列或同一斜行的性质认为是顶点之间的关系,我们可以用回溯试探的方法考虑:先依次试探每一个皇后的位置,如果有不满足条件的情况则退回,直到完成所有解的计数和输出。

用数组存储:int pos[8];
pos[0]表示第一个皇后的位置(0,1,…7)依次类推。
流程:
dfs(c)//c从0开始
for(v=0;v<8;++v)
如果pos[c]:=v满足条件,dfs(c+1);
退回之后pos[c]:=0;

这跟书上的回溯算法不太一样,因为是采用深搜的方法写的,其实思想是一致的,要仔细体会。

八皇后问题 回溯法

问题描述:
八皇后问题是十九世纪著名数学家高斯于1850年提出的。问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上。可以把八皇后问题拓展为n皇后问题,即在n*n的棋盘上摆放n个皇后,使其任意两个皇后都不能处于同一行、同一列或同一斜线上。

问题分析 :

显然,每一行可以而且必须放一个皇后,所以n皇后问题的解可以用一个n元向量X=(x1,x2,…..xn)表示,其中,1≤ i≤ n且1≤ xi≤ n,即第n个皇后放在第i行第xi列上。

由于两个皇后不能放在同一列上,所以,解向量X必须满足的约束条件为:

xi≠ xj;

若两个皇后的摆放位置分别是(i,xi)和(j,xj),在棋盘上斜率为-1的斜线上,满足条件i-j=xi-xj;在棋盘上斜率为1的斜线上,满足条件i+j=xi+xj;

综合两种情况,由于两个皇后不能位于同一斜线上,所以,

解向量X必须满足的约束条件为:

|i-xi|≠ |j-xj|

代码如下:

#include<stdio.h>
#include<math.h>
int x[100];
bool place(int k)//考察皇后k放置在x[k]列是否发生冲突
{
    int i;
    for(i=1;i<k;i++)
        if(x[k]==x[i]||abs(k-i)==abs(x[k]-x[i]))
            return false;
        return true;
}

void queue(int n)
{
    int i,k;
    for(i=1;i<=n;i++)
        x[i]=0;
    k=1;
    while(k>=1)
    {
        x[k]=x[k]+1;   //在下一列放置第k个皇后
        while(x[k]<=n&&!place(k))
            x[k]=x[k]+1;//搜索下一列
        if(x[k]<=n&&k==n)//得到一个输出
        {
            for(i=1;i<=n;i++)
                printf("%d ",x[i]);
            printf("\n");
        //return;//若return则只求出其中一种解,若不return则可以继续回溯,求出全部的可能的解
        }
        else if(x[k]<=n&&k<n)
            k=k+1;//放置下一个皇后
        else
        {
            x[k]=0;//重置x[k],回溯
            k=k-1;
        }
    }
}

void main()
{
   int n;
   printf("输入皇后个数n:\n");
   scanf("%d",&n);
   queue(n);
}
时间: 2024-10-24 04:37:11

穷举搜索:回溯与深搜的相关文章

深搜算法实例:老鼠走迷宫(一)

这个是简单的深搜,应该输入深搜中抛砖型的,联系下代码,回顾一下深搜的思想. 本题的要求是,在开始点(1,1)和终点(5,5)放一只老鼠,让老鼠找到一条路径走出去(暂时不考虑最短路径),找到后输出路径. 最简单的想法就是对于上下左右四个进行刨根型的搜索,找到就返回输出,进入死胡同了就原路返回,找最近的有其他路径的点,继续搜索,知道找出为止. 下面是代码部分. #include <stdio.h> #include <stdlib.h> #define SUCCESS 1 #defin

acm-邻接矩阵能进行深搜么。现在会邻接表的深搜,还用把邻接矩阵转化为邻接表吗

问题描述 邻接矩阵能进行深搜么.现在会邻接表的深搜,还用把邻接矩阵转化为邻接表吗 邻接矩阵如果能进行的话.麻烦大神给点代码啊.小白..如题...... 解决方案 void dfs(int i){ visited[i]=1; for(int j=0;j<n;j++){ if(G[i][j]==1&&visited[j]==0){ dfs(j); } } } 解决方案二: 这是用邻接矩阵求最小生成树的,题主看下能否帮的上忙,如果能帮的上,希望可以采纳 #include #include

c++-UVa1374快速幂运算迭代深搜法 ,C++初学者,求优化方法

问题描述 UVa1374快速幂运算迭代深搜法 ,C++初学者,求优化方法 这是我的代码,优化过几次,但是还是很慢很慢,求大神给优化途经,就是在我的代码的进行优化 #include #include #include #include using namespace std; bool search(int,set&,int dep,int); int MAX=1; int tempMax; int main() { sets;int n; for(n=2;n!=1000;++n) { s.cle

HDOJ/HDU 1242 Rescue(经典BFS深搜-优先队列)

Problem Description Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison. Angel's friends want to save Angel. Their task is: approa

HDOJ/HDU 1015 Safecracker(深搜)

Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Klein safe behind a painting in the second-floor library. Klein safes are extremely rare; most of them, along with Klein and his factory, were destroyed in Wo

ZOJ(ZJU) 1002 Fire Net(深搜)

Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall. A blockhouse is a small castle that has four openings through which to shoot. The fo

深搜回溯-素数环-1459-jobdu

题目1459:Prime ring problem 时间限制:2 秒内存限制:128 兆特殊判题:否提交:747解决:306 题目描述: A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime. No

HDOJ1181变形课 深搜回溯

变形课 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 18474 Accepted Submission(s): 6663 Problem Description 呃--变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个统一规律:如果咒语是以a

HDOJ1518Square 深搜

Square Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11099 Accepted Submission(s): 3566 Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-end to f