说明
留个纪念,记录部分大连理工大学算法设计与分析课程源代码。
本人代码水平有限,可能会有错误,请评论区交流讨论。
给学弟学妹一些方便,或者是有基础算法需求的朋友。编程语言c++。
本系列总目录
注意:参考书:王晓东《算法设计与分析第四版》
- 递归与分治算法
- 动态规划
- 贪心算法
- 回溯算法
本部分目录
1.回溯理解
回溯,又可以说深度优先搜索,暴搜,是一种通用的求解框架。
回溯法求解一般步骤:
1.定义问题的解空间
2.确定易于搜索的解空间结构
3.以DFS的方式搜索解空间,用剪枝函数(减去子树或限界函数)避免无效搜索。
既然是DFS就可以由递归和非递归(迭代)两种形式来表示。目前这些例子都是递归的代码比较容易理解。
书上又把回溯框架分为两种,一种是排列树,一种是子集树。
2.回溯:全排列
//回溯法被称为一种通用的解题法,用来系统的搜索一个问题的所有解或任一解
//全排列可以说是一种最经典的应用回溯的例子
#include<iostream>
#include<algorithm>
using namespace std;
int path[11];
bool isVisited[11];
int n;
void perm(int k)
{
if(k==n+1)
{
for(int i=1;i<=n;i++)
{
cout<<path[i]<<' ';
}
cout<<endl;
}
else
{
for(int i=1;i<=n;i++)
{
if(isVisited[i]==0)
{
path[k]=i;
isVisited[i]=1;
perm(k+1);
path[k]=0;
isVisited[i]=0;
}
}
}
}
int main()
{
cin>>n;
perm(1); //第几个
return 0;
}
3.回溯:n皇后问题
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=11;
bool row[N],col[N],dg[2*N],udg[2*N];//主对角线和反对角线看成函数截距,整个映射关系就行
int n;
char g[N][N];
void Queen(int x,int y,int s)
{
if(s>n) return ;
if(y==n)
{
y=0;
x++;
}
if(x==n)
{
if(s==n)
{
for(int i=0;i<n;i++)
{
puts(g[i]);
}
puts("");
}
return ;
}
//对于每一个格子枚举放皇后与不放皇后两种选择
//不放
g[x][y]='.';
Queen(x,y+1,s);
//放
if(!row[x]&&!col[y]&&!dg[x+y]&&!udg[x-y+n])
{
g[x][y]='Q';
row[x]=col[y]=dg[x+y]=udg[x-y+n]=true;
Queen(x,y+1,s+1);
g[x][y]='.';
row[x]=col[y]=dg[x+y]=udg[x-y+n]=false;
}
}
int main()
{
cin>>n;
Queen(0,0,0);//回溯,解空间由一个个坐标拼成棋盘
return 0;
}