洛谷 P1181 数列分段 Section I

【题目链接】

洛谷 P1181 数列分段 Section I

【题目考点】

1. 贪心

【解题思路】

1. 贪心选择性质的证明

贪心选择:每次从第1个未被选择的数字开始,选择尽量长的满足加和小于等于m的子段
证明:

证明:
记整个数字序列为数组a,a[i]表示数字序列的第i个数字。

  1. 证明:存在最优解包含从第1个数字开始的尽量长的满足加和小于等于m的子段
    假设按照上述方法选择的子段为a[1]~a[g],“子段尽量长”指的是如果把a[g+1]加入到子段中,整个子段的加和就会大于m。因此选择的子段不能更长。
    如果选择的第一个子段更短也可以得到最优解,使用反证法:
    假设:最优解不包含贪心选择,存在最优解,第一个子段为a[1]~a[k],满足k<g。自然a[k+1]~a[g]不属于第一个子段。
    a[k+1]~a[g]从其它子段转到第一个子段,使第一个子段是贪心选择为a[1]~a[g]。其它子段去掉a[k+1]~a[g]的元素后,可能会使子段数量减少,可能子段中元素减少,那么该子段的加和减少或不变(因为每个元素都是非负数),不影响“每个子段加和小于等于m”的要求,子段数量不变。要求的是最少子段数量,当前已经是最优解,子段数量不变或减少,该分段仍然是最优解。该最优解包含了贪心选择,与假设相悖,原命题得证。
  2. 证明:在前k次进行贪心选择后,证明最优解包含第k+1次的贪心选择。
    证明方法同上,略。
2. 具体做法

顺序遍历数组,对于每个元素

  • 如果当前子段在添加该元素后,子段和不超过m,将该元素添加进当前子段,子段和增加该元素值
  • 否则该元素自己作为下一个子段的第一个元素,子段数量增加1。
    最后输出子段数

【题解代码】

解法1:贪心
#include<bits/stdc++.h>
using namespace std;
#define N 100005
int n, m, a[N];
int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; ++i)
		cin >> a[i];
	int sum = 0, ct = 1;
	for(int i = 1; i <= n; ++i)
	{
		if(sum+a[i] <= m)
			sum += a[i];
		else
		{
			ct++;
			sum = a[i];	
		}
	}
	cout << ct;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值