CF545C Woodcutters

CF545C Woodcutters

洛谷传送门

题意翻译

给 n 棵树在一维数轴上的坐标,以及它们的长度。现在要你砍倒 这些树,树可以向左倒也可以向右倒,砍倒的树不能重合、当然 也不能覆盖其他的树原来的位置,现在求最大可以砍倒的树的数 目。 1 <= n <= 10^5 ; 1 <= x i , h i <= 10^9

感谢@凉凉 提供的翻译


题解:

一眼切的DP。

看到很多大佬都是用的贪心解法。所以来介绍一下DP。

DP的精髓在于转移。所以状态的设置要为转移服务。转移要保证无后效性和最优子结构。DP就是这些东西,再也没有什么其他的了。什么答案的统计都是细节问题。

那么这道题显然,针对于两棵树之间的转移,一定有第(i)棵树不砍、往左砍、往右砍这三种状态,每种状态都会对应一个最优决策,所以就直接按这个设状态:(dp[i][0/1/2])

然后按题意转移就行。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,dp[maxn][3];
struct tree
{
	int x,h;
}t[maxn];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	    scanf("%d%d",&t[i].x,&t[i].h);
	dp[1][0]=1;
    if(t[2].x-t[1].x>t[1].h) 
        dp[1][1]=1;
	for(int i=2;i<=n;i++)
	{
		dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
		if(t[i].x-t[i-1].x>t[i-1].h) 
            dp[i][0]=max(dp[i][0],dp[i-1][2]);
		if(t[i].x-t[i-1].x>t[i].h) 
            dp[i][1]=max(dp[i-1][1]+1,dp[i-1][0]+1);
		if(t[i].x-t[i-1].x>t[i].h+t[i-1].h) 
            dp[i][1]=max(dp[i][1],dp[i-1][2]+1);
		dp[i][2]=max(dp[i-1][0],dp[i-1][1])+1;
		if(t[i].x-t[i-1].x>t[i-1].h) 
            dp[i][2]=max(dp[i][2],dp[i-1][2]+1);
	}
	cout<<max(max(dp[n][0],dp[n][1]),dp[n][2]);
	return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/14037643.html