当面对“组合”,“切割”,“子集”,“排列”,“棋盘”等问题时,我们可以使用回溯算法来求解,其属于纯暴力搜索,之所以会使用它,是因为通过简单的for循环暴力求解,并不能很好的求解这类问题。
因为回溯算法一般而言会使用到递归函数,所以我们可以将回溯算法看成一棵n叉树,其宽度为待处理集合的大小,其深度为递归的深度。
如:组合、切割、排列、棋盘等问题,都是获取的叶子节点的值,而子集问题则会记录每个节点的值。
回溯算法的模板:
void backtracking(参数)
{
if(终止条件)
{
收集结果;
return;
}
for(集合元素)
{
处理节点;
递归函数;
回溯操作;
}
return;
}
以下是加起来和为目标值的组合问题在牛客网上的地址
加起来和为目标值的组合
void backtracking(vector<int> &num,int target,int m,int cur)//参数
{
if(cur==target)//终止条件
{
ans.emplace_back(res);//收集结果
return;
}
else
{
for(int i=m;i<num.size();i++)//遍历集合元素
{
if(cur+num[i]>target)//剪枝
break;
if(i>m && num[i-1]==num[i])//去重
continue;
else{
res.emplace_back(num.at(i));//处理节点
DFS(num,target,i+1,cur+num.at(i));//递归函数
res.pop_back();//回溯操作
}
}
}
return;
}
参考:
带你学透回溯算法(B站)