回溯算法建立在DFS基础之上的,但不同的是在搜索过程中,达到结束条件后,恢复状态,回溯上一层,再次搜索
当问题需要"回头",以此来查找出所有的解的时候,使用回溯算法。
即满足结束条件或者发现不是正确路径的时候(走不通),要撤销选择,回退到上一个状态,继续尝试,直到找出所有解为止
回溯算法模板
void dfs()//参数用来表示状态
{
if(到达终点状态)
{
...//根据题意添加
return;
}
if(越界或者是不合法状态)
return;
if(特殊状态)//剪枝
return ;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改操作;//根据题意来添加
标记;
dfs();
(还原标记);
//是否还原标记根据题意
//如果加上(还原标记)就是 回溯法
}
}
}
任何大于1的自然数n,都可以拆分为若干小于n的自然数之和。
const int MAXN = 10 + 2;
int path[MAXN] = { 1 };
void dfs_equation1(int s, int n, int bits, int& sum)
{
for (int i = path[bits - 1]; i <= s; ++i) // 确保path[] 升序,有[path[bits - 1], s]中可能
{
if (i < n)
{
path[bits] = i;
s -= i;
if (s == 0)
{
++sum;
for (int j = 1; j <= bits; ++j)
std::cout << path[j] << " ";
std::cout << std::endl;
}
else if (s > 0)
{
dfs_equation1(s, n, bits + 1, sum);
}
s += i; //回溯还原相关状态
}
}
}
void dfs_equation1_1(int s, int n, int bits, int& sum)
{
if (s == 0)
{
++sum;
for (int j = 1; j < bits; ++j)
std::cout << path[j] << " ";
std::cout << std::endl;
}
for (int i = path[bits - 1]; i <= s; ++i) // 确保path[] 升序,有[path[bits - 1], s]中可能
{
if (i < n)
{
path[bits] = i;
dfs_equation1_1(s-i, n, bits + 1, sum); // s-i 放在参数中,不需要手动回溯还原相关状态
}
}
}
int main()
{
int sum = 0;
dfs_equation1(4, 4, 1, sum);
std::cout << sum << std::endl;
sum = 0;
dfs_equation1_1(4, 4, 1, sum);
std::cout << sum << std::endl;
return 0;
}
1 1 1 1
1 1 2
1 3
2 2
4
1 1 1 1
1 1 2
1 3
2 2
4
在1到9之间插入“+”或“-”或者不插入任何符号,
使等式1 2 3 4 5 6 7 8 9 = 108成立
#include <iostream>
#include <vector>
const int MAXN = 10 + 2;
int sign[MAXN] = { 0 };
int calc()
{
int tmp = 0, sum = 1, i = 1, j = 0;
bool flag = true;
std::vector<int> vec;
vec.push_back(1);
for (i = 1; i <= 8; ++i)
if (sign[i] == 0)
vec[vec.size() - 1] = vec[vec.size() - 1] * 10 + (i + 1);
else
vec.push_back(i + 1);
i = 1;
j = 0;
sum = vec[j];
while (i <= 8)
{
if (sign[i] == 1)
sum += vec[++j];
else if (sign[i] == 2)
sum -= vec[++j];
++i;
}
return sum;
}
void dfs_equation2(int layers, int res, int& total)
{
if (layers > 8)
{
int sum = calc();
if (res == sum)
{
++total;
std::cout << 1;
int tmp = 1;
for (int i = 1; i <= 8; ++i)
{
if (sign[i] == 1)
std::cout << "+";
else if (sign[i] == 2)
std::cout << "-";
std::cout << (i + 1);
}
std::cout << "=" << sum << std::endl;
}
return;
}
for (int i = 0; i < 3; ++i) // 0:null, 1:+, 2:-
{
sign[layers] = i;
dfs_equation2(layers + 1, res, total);
}
}
int main()
{
int res = 108;
int total = 0;
dfs_equation2(1, res, total);
std::cout << total << std::endl;
return 0;
}
123+4-5-6-7+8-9
123-45+6+7+8+9
123-4+5-6+7-8-9
12+34+56+7+8-9
12+3+4+5+67+8+9
12+3-4-5+6+7+89
12-3+4+5-6+7+89
1+23+4+56+7+8+9
1+23+4+5+6+78-9
1+23-4-5+6+78+9
1+2+34+5+67+8-9
1+2+34-5-6-7+89
1+2+3+4+5+6+78+9
1+2-3+45-6+78-9
1-2-34+56+78+9
15