CF545C Woodcutters (#线性dp)

题目描述

Little Susie listens to fairy tales before bed every day. Today's fairy tale was about wood cutters and the little girl immediately started imagining the choppers cutting wood. She imagined the situation that is described below.

There are nn trees located along the road at points with coordinates x_{1},x_{2},...,x_{n}x1​,x2​,...,xn​ . Each tree has its height h_{i}hi​ . Woodcutters can cut down a tree and fell it to the left or to the right. After that it occupies one of the segments [x_{i}-h_{i},x_{i}][xi​−hi​,xi​] or [x_{i};x_{i}+h_{i}][xi​;xi​+hi​] . The tree that is not cut down occupies a single point with coordinate x_{i}xi​ . Woodcutters can fell a tree if the segment to be occupied by the fallen tree doesn't contain any occupied point. The woodcutters want to process as many trees as possible, so Susie wonders, what is the maximum number of trees to fell.

输入格式

The first line contains integer nn ( 1<=n<=10^{5}1<=n<=105 ) — the number of trees.

Next nn lines contain pairs of integers x_{i},h_{i}xi​,hi​ ( 1<=x_{i},h_{i}<=10^{9}1<=xi​,hi​<=109 ) — the coordinate and the height of the і -th tree.

The pairs are given in the order of ascending x_{i}xi​ . No two trees are located at the point with the same coordinate.

输出格式

Print a single number — the maximum number of trees that you can cut down by the given rules.

题意翻译

给 n 棵树在一维数轴上的坐标,以及它们的长度。现在要你砍倒 这些树,树可以向左倒也可以向右倒,砍倒的树不能重合、当然 也不能覆盖其他的树原来的位置,现在求最大可以砍倒的树的数 目。 1 <= n <= 10^5 ; 1 <= x i , h i <= 10^9

感谢@凉凉 提供的翻译

输入输出样例

输入 #1复制

5
1 2
2 1
5 10
10 9
19 1

输出 #1复制

3

输入 #2复制

5
1 2
2 1
5 10
10 9
20 1

输出 #2复制

4

说明/提示

In the first sample you can fell the trees like that:

  • fell the 11 -st tree to the left — now it occupies segment [-1;1][−1;1]
  • fell the 22 -nd tree to the right — now it occupies segment [2;3][2;3]
  • leave the 33 -rd tree — it occupies point 55
  • leave the 44 -th tree — it occupies point 1010
  • fell the 55 -th tree to the right — now it occupies segment [19;20][19;20]

In the second sample you can also fell 44 -th tree to the right, after that it will occupy segment [10;19][10;19] .


思路

题意:现在有n棵树,对应每个树都有一个位子,并且有一个对应的高度,现在我们想砍最多数量的树,使得其倒下之后,不会压倒其他的树,树可以向左倒下,也可以向右倒下。

令dp[i][0]为第i棵树向左倒的最多能砍掉的树,dp[i][1]为第i棵树向右倒的最多能砍掉的树,则:

1.不砍,第i-1树的最优状态转移到第i棵(本质上是预处理,为2,3,4情况服务)

dp[i][0]=dp[i][1]=max(dp[i-1][0],dp[i-1][1])

2.第i棵向左倒,第i-1棵也向左倒

当a[i].position-a[i].height>a[i-1].position时

dp[i][0]=max(dp[i][0],dp[i-1][0]+1)

不砍或砍。

3.第i棵向左倒,第i-1棵向右倒

当a[i].position-a[i].height>a[i-1].position+a[i-1].height时

dp[i][0]=max(dp[i][0],dp[i-1][1]+1)

不砍或砍。

4.第i棵向右倒

当a[i].position+a[i].height<a[i+1].position时

dp[i][1]=dp[i][1]+1

答案为max(dp[n][0],dp[n][1])。

#include <stdio.h>
#include <iostream>
#define N 100001
#define inf 2e9+7
using namespace std;
struct node
{
	int position,height;
}a[N];
int dp[N][2],n,s;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a[i].position>>a[i].height;
	}
	a[n+1].height=inf;
	a[n+1].position=inf;
	a[0].height=-inf;
	for(i=1;i<=n;i++)
	{
		dp[i][1]=dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
		if(a[i].position-a[i].height>a[i-1].position)
		{
			dp[i][0]=max(dp[i][0],dp[i-1][0]+1);
		}
		if(a[i].position-a[i].height>a[i-1].position+a[i-1].height)
		{
			dp[i][0]=max(dp[i][0],dp[i-1][1]+1);
		}
		if(a[i].position+a[i].height<a[i+1].position)
		{
			dp[i][1]++;
		}
	}
	cout<<max(dp[n][0],dp[n][1])<<endl;
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值