一、解空间树结构
深度优先遍历——回溯法
广度优先遍历——分支限界法
二、剪枝函数
2.1 约束函数 —— 剪去 不含可行解
2.1.1显式约束 解空间
2.1.2隐式约束 找出所有可行解
2.2 限界函数 —— 剪去 不含最优解
三、经典问题
1.N皇后问题
1.xi != xj //不同行不同列
2.|i - j| != |xi - xj| //不放对角线
int place(int j)
{
for (i = 1; i < j; i++)
//保证不同行不同列,且不在对角线
if (abs(j - i) == abs(x[j] - x[i]) || x[j] == x[i])
return 0;
return 1;
}
void queen(int t) // 放第t个皇后
{
if (t > n)
sum++; // 可行解个数加1
else
for (int j = 1; j <= n; j++)
{
x[t] = j; // 第t个皇后放在第j列
if (place(t))
queen(t + 1);
}
}
2.n皇后问题的表格
2.子集和数问题
i j k
i:已装入
j:下一个要考虑的下标
k:剩余元素之和
条件:
1.i + wj <= M 不能超过总数
2.i + k >= M 不能剩余的加起来够不到总数
3.图着色问题
四色定理:一张地图至少需要四种颜色进行着色 可以保证相邻两个国家颜色不同
-
哈密顿环,找一笔能够画到底的问题
有哈密顿环:
无哈密顿环:
下面给出关键步骤的代码:
对应的解空间是一棵m叉树子集树,高度为n,层次i从1开始。
当顶点i与顶点j有边时,置a[i][j]=1,其他情况置 a[i][j]=0。
bool is_notSame(int i) // 判断顶点i是否与相邻顶点着色不同
{
for (int j = 1; j <= n; j++)
// a[i][j] == 1 有边,意思是相邻
// && x[i] == x[j] 即相邻且同色 返回false
if (a[i][j] == 1 && x[i] == x[j])
return false;
return true;
}
// 求解图的m着色问题
void dfs(int i)
{
if (i > n) // 达到叶子结点
count++; // 着色方案数增1
else
{
for (int j = 1; j <= m; j++) // 试探每一种着色
{
x[i] = j; // 试探着色j
if (is_notSame(i)) // 不同色,可以着色j,进入下一个顶点着色
dfs(i + 1);
x[i] = 0; // 回溯
}
}
}