DFS之剪枝与优化

DFS之剪枝与优化

dfs和bfs都是对应一个搜索树,常用的剪枝策略:
①优化搜索顺序:大部分情况下,我们应该优先搜索分支较少的节点。
②排除等效冗余
③可行性剪枝
④最优性剪枝
⑤记忆化搜索(dp)

165. 小猫爬山

翰翰和达达饲养了 N只小猫,这天,小猫们要去爬山。
经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。
翰翰和达达只好花钱让它们坐索道下山。
索道上的缆车最大承重量为 W,而 N只小猫的重量分别是 C1、C2……CN。
当然,每辆缆车上的小猫的重量之和不能超过 W。
每租用一辆缆车,翰翰和达达就要付 1美元,所以他们想知道,最少需要付多少美元才能把这 N只小猫都运送下山?

输入格式
第 1行:包含两个用空格隔开的整数,N和 W。
第 2…N+1行:每行一个整数,其中第 i+1行的整数表示第 i只小猫的重量 Ci。

输出格式
输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。

数据范围
1≤N≤18,
1≤Ci≤W≤10^8
输入样例:
5 1996
1
2
1994
12
29
输出样例:
2

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 20;

int n,m;
int w[N];
int sum[N];
int ans=N;

void dfs(int u,int k){
   
    //最优性剪枝
    if(k>=ans) return ;
    if(u==n){
   
        ans=k;
        return;
    }
    for(int i=0;i<k;i++){
   
        if(sum[i]+w[u]<=m){
   //可行性剪枝
            sum[i]+=w[u];
            dfs(u+1,k);
            sum[i]-=w[u];//恢复现场
        }
    }
    sum[k]=w[u];
    dfs(u+1,k+1);
    sum[k]=0;//恢复现场
}

int main(){
   
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>w[i];
    //优化搜索顺序
    sort(w,w+n);
    reverse(w,w+n);
    dfs(0,0);//从零号猫,当前车的数量是0开始搜索
    cout<<ans<<endl;
    return 0;
}

166. 数独

数独 是一种传统益智游戏,你需要把一个 9×9的数独补充完整,使得数独中每行、每列、每个 3×3的九宫格内数字 1∼9均恰好出现一次。
请编写一个程序填写数独。
输入格式
输入包含多组测试用例。
每个测试用例占一行,包含 81个字符,代表数独的 81个格内数据(顺序总体由上到下,同行由左到右)。
每个字符都是一个数字(1−9)或一个 .(表示尚未填充)。
您可以假设输入中的每个谜题都只有一个解决方案。
文件结尾处为包含单词 end 的单行,表示输入结束。
输出格式
每个测试用例,输出一行数据,代表填充完全后的数独。
输入样例:
4…8.5.3…7…2…6…8.4…1…6.3.7.5…2…1.4…
…52…8.4…3…9…5.1…6…2…7…3…6…1…7.4…3.
end
输出样例:
417369825632158947958724316825437169791586432346912758289643571573291684164875293
416837529982465371735129468571298643293746185864351297647913852359682714128574936
解题思路
位运算优化:行,列,九宫格,都可以用9个二进制数表示(1表示可放,0表示不能放),只有三者取&后,如果仍为1,才能放进去.

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 9,M = 1<<N;

int ones[M],map[M];
int row[N
### 关于DFS剪枝优化方法 #### DFS剪枝的概念 深度优先搜索(Depth First Search, DFS)是一种用于遍历或搜索树或图的算法。该算法尝试深入探索每一个节点直到无法继续为止,再回溯到上一个节点并重复此过程。然而,在解决实际问题时,未经优化DFS可能会遇到状态空间爆炸的问题,导致效率低下甚至超时。 为了提升性能,可以采用剪枝技术来减少不必要的计算路径。具体来说,就是当发现当前分支不可能得到更优解时提前终止其扩展[^1]。 #### 剪枝策略的应用实例 对于给定条件下的圆柱体体积固定而表面积最小化问题,可以通过合理设置r和h之间的增长关系来进行有效剪枝。即规定每次迭代中的半径\( r_i \) 和高度 \( h_i \) 应满足严格递增的关系:\[ r(i)<r(i+1),\quad h(i)<h(i+1)\] 这种做法不仅简化了逻辑判断流程,而且有助于避免重复访问相同的状态组合,从而提高了整体求解速度。 #### C++实现示例 下面是一个简单的C++代码片段展示如何利用上述原则实施DFS剪枝: ```cpp #include <iostream> using namespace std; void dfs(int depth, int n, double &minSurfaceArea){ if (depth >= minSurfaceArea || !canFormVolume(n)) return; // 尝试不同的r,h组合... } int main(){ double minSurfaceArea = DBL_MAX; int volume = /* 输入目标体积 */; dfs(0, volume, minSurfaceArea); } ``` 在此基础上还可以进一步考虑其他形式的剪枝措施,比如基于贪心思想预先排除明显不合理的候选方案;或是引入记忆化机制防止多次处理同一组参数等[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值