codeforces#303-C. Woodcutters-贪心

http://codeforces.com/contest/545/problem/C


题意:

给你n棵树{x,h} x是其坐标,h是高度

现在如果砍下第xi棵树,那么你可以让她往左倒下或者往右倒下, 这会形成一个区间[xi - hi, xi] or [xi;xi + hi]

能砍下这棵树的条件就是, 砍下之后形成的区间不包含任何别的树

思路:

贪心解决,从左到右贪心,先判断 【x-h,x】、【x,x+h】里是否有树

如果前者没,则说明可以往左倒,后者没,则可以往右倒  

(我们要尽量让树往左倒,这样才能尽量得到最优解)

可以往左倒时,如果前面的树往左倒,则当前的树一定可以往左倒,否则,如果满足前面的树倒下的区间和当前的树倒下的区间不重合,也可以往左,其余就不可以了

当所有往左的情况都不合法时,那么只能往右倒或者无法倒了

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std; 
struct node
{
	int x,h,num;
	int dir;
	node(){}
	node(int a,int b,int c)
	{x=a;h=b;num=c;}
};

int kill[100005];  
int min(int a,int b)
{
	return a<b?a:b;
} 

node tm[100005];  
int main()
{   
	int i,j,n;
	scanf("%d",&n);
	for (i=1;i<=n;i++)
	{
		scanf("%d%d",&tm[i].x,&tm[i].h); 
	} 
	for (i=1;i<=n;i++)
	{
		int f=tm[i].x;
		int d=tm[i].h;
		int cun1=0;
		int cun2=0;
		j=i+1;
		if (j<=n&&tm[j].x<=f+d)
		{
			cun1=1;
		}
		j=i-1;
		if (j>=1&&tm[j].x>=f-d)
		{
			cun2=1;
		} 
		if (!cun2&&!cun1)
		{
				if (i==1) {tm[i].dir=1;continue;}
		
			if (tm[i-1].dir==1||!tm[i-1].dir) 
				tm[i].dir=1; 
			else
			if (tm[i-1].dir==2&&tm[i-1].x+tm[i-1].h<tm[i].x-tm[i].h )
				tm[i].dir=1;
			else
				tm[i].dir=2;
				
			
		}
		else
		if (cun2==0)	//left
		{
			if (i==1) {tm[i].dir=1;continue;}
			
			if (tm[i-1].dir==1||!tm[i-1].dir)//left 
				tm[i].dir=1; 
			else	//前一个往右倒
			{
				if (tm[i-1].dir==2&&tm[i-1].x+tm[i-1].h<tm[i].x-tm[i].h) // 互不相压
				tm[i].dir=1;				//可以往左 
				else
					kill[i]=1;  //无法砍下
			}
		}
		else
			if (cun1==0)	//right 
			{
				tm[i].dir=2;  
			}
			else
				kill[i]=1; //无法砍下

	}  
	int ans=0;
	for (i=1;i<=n;i++)
	{
		if (kill[i]==0)
			ans++;
	} 


	printf("%d\n",ans);
	
	
	
	
	
	
	return 0;
	
}



你可能感兴趣的:(codeforces#303-C. Woodcutters-贪心)