小猫爬山-DFS

目录

1.题目描述

2.题意

3.解题思路

4.代码实现


1.题目描述

题目来源:acwing

翰翰和达达饲养了 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≤1e8

输入样例:

5 1996
1
2
1994
12
29

输出样例:

2

2.题意

题意:将输入的这n只重量不完全相同的小猫,进行组合放进数台负重为W的缆车上,输出所需的最少缆车的租金(一辆缆车的租金为1美元,故等价于输出所需缆车数量)

3.解题思路

通过DFS来解决这道题,首先确定其每一步的状态为已租用的缆车数和进行选择的小猫,每一步的选择1为将该小猫放入已租的缆车,2为将小猫放入新租的缆车。问题边界为,所有的小猫已完成选择。

剪枝1:若发现当前状态已租用的缆车数大于等于已记录的缆车数,则结束当前状态

剪枝2:因为重量大的猫,相比于重量小的猫,能放置的缆车要更少一些,则选择重量大的猫咪先放置到缆车上,产生的状态选择会少一些,所以在DFS前,先按由重到轻的顺序对猫进行排序。

剪枝2
剪枝2

4.代码实现

cat[N]:存储输入猫咪的重量

ans:记录租用缆车最少的数量

u:表示当前属于第几只猫

k:表示当前租用缆车的个数

sum[i]:存储当前已租用的缆车i的负重

代码思路:先用cat,存储输入的猫的重量,然后用sort,将猫按重量由小到大进行排序,然后再用reverse翻转排序,然后dfs(0,0)。dfs()中的剪枝,当k>=ans时,return 。当u==n时,ans更新为k。选择1,枚举已选择的k个缆车,若猫的重量加到缆车i上不超过w,则进行dfs(u+1,k),结束枚举后,进行选择2,再租多一辆缆车,将sum[k]=cat[u],然后,dfs(u+1,k+1)。

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 20;

int n, m;
int cat[N], 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 (cat[u] + sum[i] <= m) {
			sum[i] += cat[u];
			dfs(u + 1, k);
			sum[i] -= cat[u];
		}
	}

	sum[k] = cat[u];
	dfs(u + 1, k + 1);
	sum[k] = 0;
}

int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) cin >> cat[i];
	sort(cat, cat + n);
	reverse(cat, cat + n);
	dfs(0, 0);
	cout << ans << endl;
	return 0;

}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值