Codeforces 545C Woodcutters【dp】

来源:互联网 发布:windows 确认证书 编辑:程序博客网 时间:2024/05/22 14:39

C. Woodcutters
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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 n trees located along the road at points with coordinatesx1, x2, ..., xn. Each tree has its heighthi. Woodcutters can cut down a tree and fell it to the left or to the right. After that it occupies one of the segments[xi - hi, xi] or[xi;xi + hi]. The tree that is not cut down occupies a single point with coordinatexi. 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.

Input

The first line contains integer n (1 ≤ n ≤ 105) — the number of trees.

Next n lines contain pairs of integers xi, hi (1 ≤ xi, hi ≤ 109) — the coordinate and the height of the і-th tree.

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

Output

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

Examples
Input
51 22 15 1010 919 1
Output
3
Input
51 22 15 1010 920 1
Output
4
Note

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

  • fell the 1-st tree to the left — now it occupies segment[ - 1;1]
  • fell the 2-nd tree to the right — now it occupies segment[2;3]
  • leave the 3-rd tree — it occupies point 5
  • leave the 4-th tree — it occupies point 10
  • fell the 5-th tree to the right — now it occupies segment[19;20]

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


题目大意:

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


思路:


1、维护最大数量,很显然,一棵树的向左倒下或者向右倒下,都会影响其他树摆动的方案。那么考虑dp,设定dp【i】【2】表示第i棵树:

①dp【i】【0】这棵树向左倒的情况下最多砍伐的树的数量。

②dp【i】【1】这棵树向右倒的情况下最多砍伐的树的数量。


2、那么考虑其状态转移方程:
①dp【i】【0】=max(dp【i-1】【0】,dp【i-1】【1】);dp【i】【1】=max(dp【i-1】【0】,dp【i-1】【1】)表示当前这棵树如果不砍伐的话,到第i棵树的情况。

②接下来考虑四种情况,并且需要保证每种情况下,当前树倒下之后,不会压倒其他树的部分才行:



3、对应细节要处理好,其他的就么有神马啦。


4、Ac了这个题之后百度了一发题解,发现贪心的做法比较多,这里再啰嗦一波贪心的思路:

①因为最左边的树的左边就没有树了,最右边的树的右边也没有树了,那么将最左边的树向左倒,最右边的树向右倒。

②中间的树先向左倒下,看看有没有压倒树,如果有,那么向右倒,再进行判断,如果左右两边都不行,那么这棵树就别动了。



Ac代码:

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct node{    int pos,h;}a[100050];int dp[100050][2];int cmp(node a,node b){    return a.pos<b.pos;}int main(){    int n;    while(~scanf("%d",&n))    {        for(int i=0;i<n;i++)        {            scanf("%d%d",&a[i].pos,&a[i].h);        }        a[n].pos=2000000600;        sort(a,a+n,cmp);        memset(dp,0,sizeof(dp));        for(int i=0;i<n;i++)        {            if(i==0)            {                dp[i][0]=1;                if(a[i].pos+a[i].h<a[i+1].pos)                dp[i][1]=1;            }            else            {                dp[i][1]=max(dp[i-1][1],dp[i-1][0]);                dp[i][0]=max(dp[i-1][1],dp[i-1][0]);                if(a[i].pos+a[i].h<a[i+1].pos)                dp[i][1]=max(dp[i][1],dp[i-1][0]+1);                if(a[i].pos+a[i].h<a[i+1].pos)                dp[i][1]=max(dp[i][1],dp[i-1][1]+1);                if(a[i].pos-a[i].h>a[i-1].pos)                dp[i][0]=max(dp[i][0],dp[i-1][0]+1);                if(a[i].pos-a[i].h>a[i-1].pos+a[i-1].h)                dp[i][0]=max(dp[i][0],dp[i-1][1]+1);            }        }        printf("%d\n",max(dp[n-1][1],dp[n-1][0]));    }}




0 0
原创粉丝点击