问题描述:学校里新进了一批书,由班长负责发放到每个同学手中,每个人都有自己喜欢的书与不喜欢的书,班长要如发
才能使每个同学都拿到自己喜欢的图书?列出方案(几种 以及如何 分发)(*代表喜欢)
book 0 1 2 3 4
people A * * *
B * *
C * * *
D *
E * *
代码:
#include <iostream>
using namespace std;
void Try(int id); //id表示开始为第几个人分书
//全局变量
int like[5][5] = { {1, 0, 1, 1, 0},
{1, 1, 0, 0, 0},
{0, 1, 1, 0, 1},
{0, 0, 0, 1, 0},
{0, 1, 0, 0, 1} };
bool assignment[5]; //用来表示该书籍是否已经分配
int task[5], id = 0, num = 0; //task用来记录一种方案可行时每个人的书籍编号,num表示方案数
int main()
{
for (int i = 0; i < 5; i ++)
assignment[i] = false;
Try (id);
return 0;
}
void Try(int id){
if (id == 5)
{
num ++;
cout << '第' << num << "种方案" << endl;
for (int i = 0; i < 5; i ++)
cout << task[i] << ' ';
cout << endl;
return;
}
for (int book = 0; book < 5; book ++){
if (like[id][book] && !assignment[book]){
task[id] = book;
assignment[book] = true;
Try(id + 1); //递归
assignment[book] = false; //回溯
}
}
return;
}
//其问题本质山为DFS深度搜素问题,算法为递归与回溯
/*
八皇后问题分析:
八皇后相比分书问题更令人困惑的地方在于对角线 分书问题可用一个bool数组, 因此八皇后的对角线也可以使用boo l数 组表示
其难点主要在于行列与左右对角线之间的关系,即其背后的规律。
列数据分析可得:r = id + column - 1, l = id - column + 8;(id代表行,column代表列)
*/
#include <iostream>
using namespace std;
void Try(int id);
int num = 0, id = 1, task[9];
bool row[9], left_diagoud[18], right_diagoud[18];
int main()
{
for ( int i = 1; i <= 9; i ++ )
row[i] = false;
for ( int i = 1; i <= 18; i ++ ){
left_diagoud[i] = false;
right_diagoud[i] = false;
}
Try (id);
cout << "八皇后一共存在" << num << "种方案" <<endl;
return 0;
}
void Try(int id){
if (id == 9){
num ++;
cout << "方案第" << num << "种:" <<endl;
for ( int i = 1; i < 9; i ++ )
cout << task[i] << ' ';
cout << endl;
return;
}
for (int column = 1; column <= 8; column ++ ){
if (!row[column] && !right_diagoud[id + column - 1] && !left_diagoud[id - column + 8]){
task[id] = column;
row[column] = right, left_diagoud[id - column + 8] = right, right_diagoud[id + column - 1] = right;
Try (id + 1);
row[column] = false, left_diagoud[id - column + 8] = false, right_diagoud[id + column - 1] = false;
}
}
return;
}
回溯算法归纳:
回溯算法:上属于递归函数的子集,递归的下面就是回溯的过程。
回溯算法本质上是一个纯暴力的搜索,其可抽象成树形结构。
模板:
void backtracking(参数){
if (终止条件){
收集结果 || 是输出结果;
return;
}
for (集合的元素集,类似总子节点的个数){
处理节点; //对结果的处理
递归函数;
回溯操作; //本质上即将处理节点的操作进行还原
}
return;
}
```