蓝桥杯2023年第十四届省赛A组-买瓜

题目描述

小蓝正在一个瓜摊上买瓜。瓜摊上共有 n 个瓜,每个瓜的重量为 Ai 。

小蓝刀功了得,他可以把任何瓜劈成完全等重的两份,不过每个瓜只能劈一刀。

小蓝希望买到的瓜的重量的和恰好为 m 。

请问小蓝至少要劈多少个瓜才能买到重量恰好为 m 的瓜。如果无论怎样小蓝都无法得到总重恰好为 m 的瓜,请输出 −1 。

输入格式

输入的第一行包含两个整数 n, m,用一个空格分隔,分别表示瓜的个数和小蓝想买到的瓜的总重量。

第二行包含 n 个整数 Ai,相邻整数之间使用一个空格分隔,分别表示每个瓜的重量。

输出格式

输出一行包含一个整数表示答案。

样例输入

3 10
1 3 13

样例输出

2

提示

对于 20% 的评测用例,∑n≤10;

对于 60% 的评测用例,∑n≤20;

对于所有评测用例,1 ≤n≤30,1≤ Ai ≤ 10^9 ,1 ≤ m ≤ 10^9

 

整体思路

对于每一个瓜有三种选择:
1)买整个瓜
2)买半个瓜,需要增加劈瓜次数
3)不买

考虑深度优先搜索,对每个瓜的三种选择进行搜索,解空间树是一颗完全三叉树,时间复杂度为O(3^n),故需要进行剪枝。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;

const int N = 35;
int v[N]; //重量数组 
long suf[N]; // 重量数组的后缀和,即当前瓜重量加上后面所有瓜重量 
int n, m;
int ans = INT_MAX;

// 当前层数 pos,当前总重量 sum,当前劈瓜的次数 cnt 
void dfs(int pos, long sum, int cnt)
{
	if(sum == m)
	{
		ans = min(ans, cnt);
		return;
	}
	// 剪枝 
	if(pos >= n || cnt >= ans || sum > m || sum + suf[pos] < m)
	{
		return;
	}
	dfs(pos + 1, sum + v[pos], cnt); // 买整个瓜 
	dfs(pos + 1, sum + v[pos] / 2, cnt + 1); // 买半个瓜 
	dfs(pos + 1, sum, cnt); // 不买 
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	cin >> n >> m;
	m *= 2;
	for(int i = 0; i < n; i++)
	{
		cin >> v[i];
		v[i] *= 2;
	}
	sort(v, v + n, greater<int>());
	for(int i = n - 1; i >= 0; i--)
	{
		suf[i] = suf[i + 1] + v[i];
	}
	dfs(0, 0, 0);
	if(ans == INT_MAX)
	{
		cout << -1;
		exit(0);
	}
	cout << ans;
	return 0;
}

具体步骤

买半个瓜时需要将重量除 2,会产生小数,故可以将重量数组都乘 2,最大重量也乘 2。为了防止超时,将重量数组降序排列,使得更快剪枝。并创建一个重量数组的后缀数组 suf,这样在搜索时可以利用其剪枝。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值