Woodcutters
題意:
本題要你砍樹,求出一種砍樹最多的做法。樹倒後,不能和之前的樹發生重疊,也不能和沒倒的樹相撞。
反思:
- 分類時老是漏情況。
- dp時初始化很重要,這題因爲考了兩次,這次就掌握吧。
AC(貪心做法)
貪心的把
- 當前樹往左砍,能砍,pre=x【i】;
- 如果砍不了,看能不能右砍,
1)可以右砍,就pre=x【i】+h【i】;
2)不能砍的話,就pre=x【i】(因爲一棵樹不能倒在樹上,也不能和之前的樹重疊)
#include <iostream>
#include <algorithm>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
using namespace std;
const int maxn=1e5+10;
const int INF=0x7fffffff;
struct point
{
int x,a;
}p[maxn];
bool cmp(point t1, point t2)
{
return t1.x<t2.x;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n;
cin>>n;
int pre=-INF,ans=0;
For(i,1,n)cin>>p[i].x>>p[i].a;
sort(p+1,p+1+n,cmp);
p[n+1].x=INF,p[n+1].a=INF;
For(i,1,n)
{
if(p[i].x-p[i].a>pre)pre=p[i].x,ans++;
else
{
if(p[i].x+p[i].a<p[i+1].x)
{
ans++;
pre=p[i].x+p[i].a;
}
else pre=p[i].x;
}
}
cout<<ans<<endl;
return 0;
}
AC(dp)
#include <iostream>
#include <algorithm>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
using namespace std;
const int maxn=1e5+10;
int h[maxn],x[maxn];
int dp[maxn][3];
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n;
cin>>n;
For(i,1,n)cin>>x[i]>>h[i];
x[n+1]=0x7fffffff;
//初始化
dp[1][0]=1;
dp[1][2]=0;
if(x[1]+h[1]<x[2])dp[1][1]=1;
For(i,2,n)
{
dp[i][2]=max(dp[i-1][0],max(dp[i-1][1],dp[i-1][2]));
//dp[i][1]和dp[i][0]可能不會更新,但有不砍作爲中轉。
//查看向左砍
if(x[i]-h[i]>x[i-1])dp[i][0]=max(dp[i-1][0],dp[i-1][2])+1;//可以砍,查看i-1位置時的左砍和不砍
if(x[i]-h[i]>x[i-1]+h[i-1])dp[i][0]=max(dp[i][0],dp[i-1][1]+1);//如果i左砍,和i-1右砍不重合,那麼比較左砍的最優。
//右砍
if(x[i]+h[i]>=x[i+1])continue;//砍不了
dp[i][1]=max(dp[i-1][0],max(dp[i-1][1],dp[i-1][2]))+1;//砍的了,更新右砍的最值
}
cout<<max(dp[n][0],max(dp[n][1],dp[n][2]))<<endl;
return 0;
}