题目链接 https://vjudge.net/contest/214177#problem/C
题意:给定n棵树的坐标x和高度h,要求砍树,树砍倒后向左或向右躺在地上时,占的区间不能含有别的树,问最多砍多少树。
题解:dp[i][0]表示第i棵树不动,dp[i][1]表示i棵树向左倒在地上,dp[i][2]表示向右倒,dp的转移方程见代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
const int maxn = 1e5+10;
ll x[maxn], h[maxn];
int dp[maxn][5];
int main() {
scanf("%d", &n);
for(int i = 1;i <= n;i++) {
scanf("%lld%lld", &x[i], &h[i]);
}
if(n == 1) {
printf("%d\n", 1);
return 0;
}
if(x[1]+h[1] < x[2])
dp[1][2] = 1;
dp[1][1] = 1;
for(int i = 2;i <= n;i++) {
int p1 = dp[i-1][0];
int p2 = dp[i-1][1];
int p3 = dp[i-1][2];
dp[i][0] = max(p1, p2);
dp[i][0] = max(dp[i][0], p3);
if(x[i]-x[i-1] > h[i]+h[i-1]) {
dp[i][1] = dp[i][0] + 1;
} else if(x[i]-x[i-1] > h[i]) {
dp[i][1] = 1 + max(p1, p2);
}
if(i+1 <= n && x[i+1]-x[i] > h[i]) {
dp[i][2] = 1 + dp[i][0];
}
if(i == n) {
dp[i][2] = 1 + dp[i][0];
}
}
printf("%d\n", max(dp[n][2], max(dp[n][0], dp[n][1])));
return 0;
}
// dp 0 1 2
// 1 1 0
// 2 1 2
// 3 2
// 4 2
// 5 2 3 3