题目链接 http://codeforces.com/problemset/problem/545/C
题意:
一个在二维平面的伐木工想要砍尽可能的树。树有自己的坐标x[i]和高度h[i]。
如果一个树被砍下后,我们可以让它往左倒下,也可以往右倒下。
我们不移动倒下的树,树倒下后,
如果第i棵树往左倒就占据 [x[i]-h[i],x[i] ]的位置,如果往右倒,就占据[x[i],x[i]+h[i]]的位置。
如果这个区间上原本有一些其他树的占据点,那么它们就不能往这个方向倒。
一颗没有被砍的树i。占据x[i]这个点。求伐木工一次可以砍倒几颗树。
题目做法。
从左往右砍树。
如果它能往左倒,就往左砍倒它。如果能往右倒。就往右砍到它。否则不砍它。
一种贪心的思想,因为砍倒当前这棵树只对它右边的第一颗树影响。
而我们既然能砍倒它,就不用考虑影响到砍到它右边了,因为反正砍倒它+1,砍倒它后面的也+1。那样对于右边的右边的那颗树来说,无疑是这样砍是最优的。
代码如下:
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long LL;
typedef long long ll;
const int maxn = 1e6+6;
const int INF = 0x3f3f3f3f;
char str[maxn];
int a[maxn];
int dpx[maxn]; //dpx[i]记录砍到第i棵树的占据的最右边的端点
int dpnum[maxn];//dpnum[i]记录砍到第i棵的最优砍法
int h[maxn];
int x[maxn];
void show(int a[],int n){
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}printf("\n");
}
int main(){
// freopen("C:\\Users\\lenovo\\Desktop\\data.in","r",stdin);
int n;
while(scanf("%d",&n)+1){
for(int i=0;i<n;i++){
scanf("%d%d",x+i,h+i);
}
dpx[0] = x[0];//第一颗往左砍
dpnum[0] = 1;
for(int i=1;i<n;i++){
if(x[i]-h[i]>dpx[i-1]){//左砍
dpx[i] = x[i];
dpnum[i] = dpnum[i-1]+1;
}else if(i+1==n){//最后一颗直接往右砍
dpx[i] = x[i];
dpnum[i] = dpnum[i-1]+1;
}else if(x[i]+h[i]<x[i+1]){//右砍
dpx[i] = x[i]+h[i];
dpnum[i] = dpnum[i-1]+1;
}else{//不砍
dpx[i] = x[i];
dpnum[i] = dpnum[i-1];
}
}
printf("%d\n",dpnum[n-1]);
}
}