Acwing -165. 小猫爬山

翰翰和达达需将N只小猫通过缆车送下山,每辆缆车承重W,目标是最少使用缆车数量。采用深度优先搜索算法,优化小猫分配,确保最小花费。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

翰翰和达达饲养了N只小猫,这天,小猫们要去爬山。

经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。

翰翰和达达只好花钱让它们坐索道下山。

索道上的缆车最大承重量为W,而N只小猫的重量分别是C1、C2……CN。

当然,每辆缆车上的小猫的重量之和不能超过W。

每租用一辆缆车,翰翰和达达就要付1美元,所以他们想知道,最少需要付多少美元才能把这N只小猫都运送下山?

输入格式

第1行:包含两个用空格隔开的整数,N和W。

第2..N+1行:每行一个整数,其中第i+1行的整数表示第i只小猫的重量CiCi。

输出格式

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

数据范围

1≤N≤18
1≤Ci≤W≤108

输入样例:

5 1996
1
2
1994
12
29

输出样例:

2

可以用深度优先搜素解决。我们尝试依次把每一只小猫分配到一辆已经租用的缆车上,或者新租一辆缆车安置这只小猫。于是我们关心的状态有 : 已经运送的小猫有多少只,已经租用的缆车有多少辆,每辆缆车上的小猫之和。

cab[i] 表示第i个车上目前载重 . 

   1 尝试吧第 now 只小猫分配到已经租用的第 i 个 缆车上 ,如果这个缆车能装上就在 cab[i] 加上 c[now] 

   2 尝试新租一辆缆车来安置这只小猫 cab[cnt+1] = c[now] 

 加入剪枝 , 如果在搜索的过程中发现任何时刻 cnt 已经大于或者等于 已经搜到的答案,就回溯 减掉了这一分支. 

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std ;
const int MAX = 1005 ;
int n , w ;
int c[MAX] ; // 第 i 只猫的体重
int cab[MAX] ; // 第i 辆车的搭载量
int ans ;
bool cmp(const int & a , const int & b) {
	return a> b ;
}
void dfs(int now , int cnt) {
	// 正在处理第 now 只猫的分配 , 假设  前now -1 只猫已经分配好
	// 目前已经租用了 cnt 辆车
	if(cnt >= ans) return ;
	if(now == n+1) { // 所有的猫已经处理完了
		ans = min(ans,cnt) ;
		return ;
	}
	for(int i = 1 ; i<=cnt ; i++ ) {
		// 遍历所有已经租用车 ,看看哪个车能装下
		if(cab[i] +c[now] <=w ) {
			cab[i] +=c[now]  ;
			dfs(now+1,cnt) ;
			cab[i] -=c[now] ;
		}
	}
	// 新租一辆车
	cab[cnt+1] = c[now] ;
	dfs(now+1,cnt+1) ;
	cab[cnt+1] = 0 ;
}
int main(){
	cin >> n >> w;
	for(int i = 1 ; i<=n;i++) cin >> c[i] ;
	sort(c+1,c+1+n ,cmp)  ;
	ans = n ; // 最多的情况是一只猫一个车
	dfs(1,0) ;
	cout<<ans <<endl ;
	
	return 0 ;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值