1. 程式人生 > 其它 >AT5748 Robot Arms 題解

AT5748 Robot Arms 題解

分析

看到這道題,可以說被翻譯明示這是貪心題。

我們把每條線段的起點和終點算出來之後,再按照右端點從小到大排序。

證明:按右端點升序排列可以得到最優值

把右端點從左向右排,使得右端點以後的區間能有更大的空間覆蓋。

比如現在有 \(5\) 條線段,如下:

---
-
  ----
        -----
    ------

按右端點升序排序後:

-
---
  ----
    ------
        -----

最優解為:

-
  ----
         -----

如果按左端點升序排列,會發現什麼?會發現我給的樣例不好。

會發現答案還是一樣。

那麼如果把線段 \([1,3]\)

換成 \([2,5]\) 會這樣(按左端點升序排列):

-
 -----
  ----
    ------
        -----

按這個形式的最優解就為:

-
 -----

發現反例,所以得證。(偽證啊喂

程式碼

//2021/8/30

#include <iostream>

#include <cstdio>

#include <algorithm>

#define int long long

#define debug(c) cerr<<#c<<" = "<<c<<endl

namespace Newstd
{
	inline int read()
	{
		int x=0,f=1;char ch=getchar();
		while(ch<'0' || ch>'9')
		{
			if(ch=='-')
			{
				f=-1;ch=getchar();
			}
		}
		while(ch>='0' && ch<='9')
		{
			x=x*10+ch-48;ch=getchar();
		}
		return x*f;
	}
	inline void print(int x)
	{
		if(x<0)
		{
			putchar('-');x=-x;
		}
		if(x>9)
		{
			print(x/10);
		}
		putchar(x%10+'0');
	}
}

using namespace Newstd;

using namespace std;

const int ma=100005;

struct Node
{
	int l;
	
	int r;
};

Node node[ma];

inline bool cmp(Node x,Node y)
{
	return x.r<y.r;
}

#undef int

int main(void)
{
	#define int long long
	
	int n=read();
	
	for(register int i=1;i<=n;i++)
	{
		int x,L;
		
		scanf("%lld%lld",&x,&L);
		
		node[i].l=x-L;
		
		node[i].r=x+L;
	}
	
	sort(node+1,node+n+1,cmp);
	
	int now=node[1].r,ans=1;
	
	for(register int i=2;i<=n;i++)
	{
		if(node[i].l>=now)
		{
			now=node[i].r;
			
			ans++;
		}
	}
	
	printf("%lld\n",ans);
	
	return 0;
}