SDUT 2778-小明的花费预算(二分答案)

本文介绍了一种算法,旨在解决将连续月份的花费预算合理分配到若干组的问题,目标是最小化各组内的最大总花费。通过使用二分搜索技巧,文章详细展示了如何高效地找到最优解。

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

小明的花费预算

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

小明终于找到一份工作了,但是老板是个比较奇怪的人,他并不是按照每月每月的这样发工资,他觉得你想什么时候来取都可以,取的是前边连续几个月中没有取的工资,而小明恰好是一个花钱比较大手大脚的人,所以他希望每次取得钱正好够接下来的n个月的花费。
所以让你把这n个月分成正好m组。每个组至少包含一个月,每组之中的月份必须是连续的,请你为他分组,使得分得的组中最大的总花费最小。

输入

第一行是两个整数,n(1 ≤ n ≤ 100,000)和m (1 ≤ m ≤ n)
接下来的n行是连续n个月的花费,第i+1行是第i个月的花费。

输出

 输出满足最大的总花费最小的那个组的总花费。

示例输入

5 3
3
2
9
4
1

示例输出

9
初次接触二分答案,简单的说,就是对一个问题的答案,我们可以大致确定一个范围,然后在这个范围中二分,为什么可以二分呢?其实是有要求的,答案要具有单调性。就是说对于mid,经过判断后,我们可以确定答案一定是在mid左还是mid右。二分答案常用于求极大值中的最小值,极小值中的最大值等。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cctype>
#include <vector>
#include <cstdio>
#include <cmath>
#include <deque>
#include <stack>
#include <map>
#include <set>
#define ll long long
#define maxn 100010
#define pp pair<int,int>
#define  max(x,y) ( ((x) > (y)) ? (x) : (y) )
#define  min(x,y) ( ((x) > (y)) ? (y) : (x) )
using namespace std;
int n, m, a[maxn], high, low;
bool jduge(int mid)
{
	int cnt = 1, s = 0;

	for (int i = 0; i < n; i++) {
		if (s + a[i] <= mid) {
			s += a[i];
		} else {
			cnt++;
			s = a[i];
		}
	}

	if (cnt <= m) {
		return 1;
	} else {
		return 0;
	}

}
void solve()
{
	int mid;

	while (low <= high) {
		mid = (low + high) / 2;

		if (jduge(mid)) {
			high = mid - 1;
		} else {
			low = mid + 1;
		}
	}

	printf("%d\n", mid);
}
int main()
{
	while (~scanf("%d%d", &n, &m)) {
		high = 0;
		low = 0;

		for (int i = 0; i < n; i++) {
			scanf("%d", a + i);
			low = max(a[i], low);
			high += a[i];
		}

		solve();
	}

	return 0;
}
### 关于山东理工大学C语言实验中的二分查找题目 在学习C语言的过程中,二分查找是一种非常重要的算法。它通常用于在一个有序数组中快速定位目标值的位置。以下是关于山东理工大学可能涉及的C语言实验——二分查找的相关题目及其解析。 #### 二分查找基本原理 二分查找的核心思想是通过不断缩小搜索范围来提高效率。假设有一个已排序的数组`arr[]`以及要查找的目标值`target`,则可以通过以下方式实现: 1. 定义两个指针分别指向数组的起始位置和结束位置。 2. 计算中间索引并比较该处的值与目标值的关系。 3. 如果相等,则返回索引;如果小于目标值,则调整左边界;如果大于目标值,则调整右边界。 4. 循环上述过程直到找到目标或者确认不存在目标值为止[^1]。 ```c int binarySearch(int arr[], int n, int target) { int left = 0; int right = n - 1; while (left <= right) { int mid = left + (right - left) / 2; // 防止溢出 if (arr[mid] == target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; // 表示未找到 } ``` 此函数实现了标准的二分查找逻辑,并适用于任何升序排列的数据集。 #### 可能的SDUT C语言实验题目描述 基于常见的教学需求,可以推测如下类型的练习题可能会出现在山东理工大学(C language lab): **题目**: 给定一个长度为N(1 ≤ N ≤ 1e5) 的整数序列A_i (-1e9 ≤ A_i ≤ 1e9),这些数字已经按照从小到大顺序给出。另外还有Q次询问(1 ≤ Q ≤ 1e5),每次询问提供一个X(-1e9 ≤ X ≤ 1e9), 要求判断这个数值是否存在于此列表当中。如果有多个相同的元素满足条件只需要输出任意一个即可。 对于这个问题,显然应该采用高效的二分查找方法解决而不是简单的线性扫描法(O(N))因为后者无法承受如此大规模输入数据量下的时间复杂度要求O(Q*N)[^1]. --- #### 解析样例程序代码片段 下面展示了一个针对上述假想问题的具体解决方案: ```c #include<stdio.h> // 原型声明 int binary_search(const int *array,int size,int value); int main(){ int num_elements,q,x,i,j,k,temp_array[100005]; scanf("%d",&num_elements); for(i=0;i<num_elements;i++)scanf("%d",temp_array+i); scanf("%d",&q); while(q--){ scanf("%d",&x); j=binary_search(temp_array,num_elements,x); printf("%s\n",(j>=0?"YES":"NO")); } } /* 返回下标 若找不到就返回-1 */ int binary_search(const int *array,int size,int value){ register int l,r,m; l=0;r=size-1; while(l<=r){ m=(l+r)>>1;//位运算代替除法提升性能 if(array[m]==value)return m; array[m]<value?(l=m+1):(r=m-1); } return -1; } ``` 以上源码展示了如何利用二分查找技术高效处理大量查询请求的情况。注意这里还运用了一些优化技巧比如使用移位操作替代普通的除以2计算从而加快执行速度等等。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值