算法标签:dfs+剪枝优化
题目链接:小猫爬山
题目大意:已知一辆缆车的最大承受重量和m只猫的重量,求最少需要多少量缆车
思路:按体重从大到小枚举每只小猫(优化搜索顺序),每只小猫有两种选择,可以选则加入之前的缆车,如果可以加入的话(可行性剪枝),也可以选择自己额外开一辆缆车。当枚举到最后一只的时候,更新一下res,如果搜索过程中,当前缆车数量已经>=res,直接返回(最优性剪枝)
那为什么按从大到小能优化搜索呢?
我的理解是:如果先搜大的,后面就只能搜小的,如果先搜小的话,后面即可以搜大的也可以搜小的,这样搜分支显然比先搜大的多很多,所以先搜大的能够优化搜索。
代码如下:
#include<bits/stdc++.h> using namespace std; #define sf(x) scanf("%lld",&x) #define sff(x,y) scanf("%lld%lld",&x,&y) #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define pii pair<int,int> #define f first #define s second #define int long long const int N=20; int m,maxd; int w[N],sum[N],res=8888; bool cmp(int a,int b) { return a>b; } void dfs(int u,int now) { if(now>=res)//最优性剪枝 return ; if(u==m) { res=min(res,now); return; } //加到别的组 for(int i=1;i<=now;i++) { if(sum[i]+w[u]<=maxd)//可行性剪枝 { sum[i]+=w[u]; dfs(u+1,now); sum[i]-=w[u]; } } //自创一组 sum[now+1]=w[u]; dfs(u+1,++now); sum[now+1]=0; } signed main() { sff(m,maxd); for(int i=0;i<m;i++) sf(w[i]); sort(w,w+m,cmp);//优化搜索顺序 dfs(0,0); cout<<res; }