《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;
}
View Code

 

posted @ 2021-02-15 08:29  levill  阅读(90)  评论(0编辑  收藏  举报