【搜索 折半搜索 二分】JZOJ_1252 天平

本文介绍了一种使用折半搜索算法解决特定问题的方法,即在不下降序列中找到最大值,使其不超过给定限制。通过将序列分为两半并进行搜索,再结合二分查找,可以有效地降低时间复杂度。

题意

给出一个长度为NNN的不下降序列,以及CCC,求出从这序列中取数使得最大且不超过CCC

思路

从后往前搜索,枚举选不选,再加上一点剪枝就能过掉了。

正解是折半搜索,如果直接暴力搜索,那么时间复杂度为O(2n)O(2^n)O(2n),这里NNN最大是404040,我们可以把它分成两半,做两次搜索,那么最大时间复杂度就为O(2∗220)O(2*2^{20})O(2220),然后二分一下答案就可以过掉了。

代码

#include<cstdio>
#include<algorithm>

int n, c, ans;
int a[41];
long long pre[41];

void dfs(int p, long long sum) {
	if (sum > c) return;
	if (sum + pre[p - 1] <= c) {//前面的都可以取完
		ans = std::max((long long)ans, sum + pre[p - 1]);
		return;
	}
	ans = std::max((long long)ans, sum);
	for (int i = p - 1; i >= 1; i--)
		dfs(i, sum + a[i]);
}

int main() {
	scanf("%d %d", &n, &c);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++)
		pre[i] = pre[i - 1] + a[i];
	dfs(n + 1, 0);
	printf("%d", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值