《Woodcutters》
拿到题就想dp。
状态很好想,dp[i][3] - 0 - 不砍,1 - 向左倒,2 - 向右倒
但是一开始题意读清楚,如果倒的时候有树的位置,那么就不行,并且不能和倒的重叠。
那么转移的时候首先,不砍的话就继承前面所有的。
左边倒的话还要看一下重叠。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e5 + 5; const int M = 1e3 + 5; const LL Mod = 1000000; #define pi acos(-1) #define INF 1e12 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; struct TA{ int x,h; bool operator < (const TA a) const { return x < a.x; } }p[N]; int dp[N][3],n;// - 0 - 不倒,1 - 向左倒,2 - 向右倒 int main() { n = read(); for(int i = 1;i <= n;++i) p[i].x = read(),p[i].h = read(); sort(p + 1,p + n + 1); dp[1][0] = 0,dp[1][1] = 1; if(p[2].x > p[1].x + p[1].h) dp[1][2] = 1; else dp[1][2] = 0; int ans = max(dp[1][1],dp[1][2]); for(int i = 2;i <= n;++i) { dp[i][0] = max(dp[i - 1][0],max(dp[i - 1][2],dp[i - 1][1])); if(p[i - 1].x < p[i].x - p[i].h) { dp[i][1] = max(dp[i - 1][0],dp[i - 1][1]) + 1; if(p[i - 1].x + p[i - 1].h < p[i].x - p[i].h) dp[i][1] = max(dp[i][1],dp[i - 1][2] + 1); } else dp[i][1] = max(dp[i - 1][0],max(dp[i - 1][2],dp[i - 1][1])); if(p[i + 1].x > p[i].x + p[i].h || i == n) { dp[i][2] = max(dp[i - 1][0],max(dp[i - 1][2],dp[i - 1][1])) + 1; } else dp[i][2] = max(dp[i - 1][0],max(dp[i - 1][2],dp[i - 1][1])); ans = max(ans,max(dp[i][0],max(dp[i][1],dp[i][2]))); } //for(int i = 1;i <= n;++i) printf("dp[%d][0] is %d dp[%d][1] is %d dp[%d][2] is %d\n",i,dp[i][0],i,dp[i][1],i,dp[i][2]); printf("%d\n",ans); system("pause"); return 0; }