深搜9:【SSL】1648.登山
题目:
题目描述
小b周末和同学共 n 人去爬山,等爬到山顶的时候大家已经累的不想再走路下山了,于是决定乘坐缆车下山。
每辆缆车的最大载重量为 w,现在已知所有同学的体重,请问至少需要多少辆缆车才能将他们全部运送下山?
输入
第1行:包含两个用空格隔开的整数,n 和 w。
接下来n行,表示每位同学的体重c。
1≤n≤18
1≤ci≤w≤10^8
输出
一个整数,表示最少需要的缆车数。
样例
输入样例
5 1996
1
2
1994
12
29
输出样例
2
思路:
这道题其实我一开始是想每个人都有两种方法,进缆车或不进缆车,不进当前的缆车那就再等后面的缆车,但这样的话就会超时,因为这样做一个人可能会一直不进缆车,那就死循环了。
如果是这样的话,那该怎么搜索呢?
其实,我们可以开一个数组来记录每一辆缆车的当前状况,从1循环到x(缆车数量),如果当前缆车可以放a[p]这个人的话,就放进去试一试,或者让他自己开1辆新的缆车,最后找到用车数量最少的方案就行了。
但看一下题目,最多有18个人,18的18次方这已经远远超过1亿了,必定会超时,那有什么剪枝方法?
其实剪枝方法有很多,这里列举一个最万能的:当目前所用的缆车数≥我目前已知的最小答案,那么就return。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,w,a[20],lc[20],ans=100;
bool v[20];
void dfs(int p,int sl)
{
if(p>n)
{
ans=min(ans,sl);
return ;
}
if(sl>=ans)
return ;
for(int i=1;i<=sl;i++)
{
if(v[i]||a[p]+lc[i]>w)
continue;
lc[i]+=a[p];
if(lc[i]==w)
v[i]=true;
dfs(p+1,sl);
lc[i]-=a[p];
v[i]=false;
}
sl++;
lc[sl]=a[p];
dfs(p+1,sl);
}
int main()
{
cin>>n>>w;
for(int i=1;i<=n;i++)
cin>>a[i];
dfs(1,1);
cout<<ans;
return 0;
}


被折叠的 条评论
为什么被折叠?



