送礼物 dfs 双向dfs 剪枝 java

文章描述了一个关于搬运礼物的问题,其中达达需要在不超过特定重量限制的情况下,一次性搬运尽可能重的礼物。通过Java程序,文章实现了动态规划和搜索算法来找出这个最大重量。程序首先对礼物重量进行排序,然后进行深度优先搜索,最终得出答案。
摘要由CSDN通过智能技术生成

🍑 送礼物

达达帮翰翰给女生送礼物,翰翰一共准备了 N N N 个礼物,其中第 i i i 个礼物的重量是 KaTeX parse error: Undefined control sequence: \[ at position 2: G\̲[̲i\]

达达的力气很大,他一次可以搬动重量之和不超过 W W W 的任意多个物品。

达达希望一次搬掉尽量重的一些物品,请你告诉达达在他的力气范围内一次性能搬动的最大重量是多少。

输入格式

第一行两个整数,分别代表 W W W N N N

以后 N N N 行,每行一个正整数表示 KaTeX parse error: Undefined control sequence: \[ at position 2: G\̲[̲i\]

输出格式

仅一个整数,表示达达在他的力气范围内一次性能搬动的最大重量。

数据范围

1 ≤ N ≤ 46 1 \le N \le 46 1N46,
1 ≤ W , G [ i ] ≤ 2 31 − 1 1 \le W,G[i] \le 2^{31}-1 1W,G[i]2311

输入样例:
20 5
7
5
4
18
1
输出样例:
19

在这里插入图片描述

import java.util.*;

class Main
{
	static int N = 100;
	static int n, m, k;
	static Integer[] w = new Integer[N];
//	static int[] ww = new int[1 << 25];// 存储能凑出的重量
	static Integer[] ww = new Integer[1 << 25];
	static HashSet<Integer> set = new HashSet<>();// 实现去重
	static int cnt, ans;// cnt 记录能凑出的重量数

	/**
	 * @param u 当前枚举的物品(未计算)
	 * @param s 当前的总重量
	 */
	static void dfs1(int u, int s)
	{
		if (u == k)
		{
			set.add(s);// 把重量存在 HashSet 里边去
			return;
		}

		dfs1(u + 1, s);

		if ((long) s + w[u] <= m)
			dfs1(u + 1, s + w[u]);
	}

	/**
	 * @param u 表示当前枚举到的物品
	 * @param s 表示当前方案的总体积
	 */
	static void dfs2(int u, int s)
	{
		if (u == n)
		{
			int l = 0;
			int r = cnt - 1;
			while (l < r)
			{
				int mid = l + r + 1 >> 1;
//				找到 最大的 小于等于 (m-s) 的数
				if (ww[mid] <= m - s)
					l = mid;
				else
					r = mid - 1;
			}
			ans = Math.max(ans, ww[l] + s);
			return;
		}
		dfs2(u + 1, s);
		if ((long) s + w[u] <= m)
			dfs2(u + 1, s + w[u]);
	}

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		m = sc.nextInt();// 总体积
		n = sc.nextInt();// 物品个数
		for (int i = 0; i < n; i++)
			w[i] = sc.nextInt();
		Arrays.sort(w, 0, n, (o1, o2) -> o2 - o1);// 从大到小进行排序
		k = n / 2 ;
		dfs1(0, 0);
		cnt = 1;
		//Integer数组进行排序时一定要初始化为一个值,就算是全局数组也没有默认值
		ww[0] = 0;
		for (int x : set)
			ww[cnt++] = x;
		Arrays.sort(ww, 0, cnt, (o1, o2) -> o1-o2);// 这次是从小到大进行排序
		dfs2(k, 0);
		System.out.println(ans);
	}
}

👨‍🏫 Bug-Free 的题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值