AT5748 Robot Arms 題解
阿新 • • 發佈:2021-08-31
分析
看到這道題,可以說被翻譯明示這是貪心題。
我們把每條線段的起點和終點算出來之後,再按照右端點從小到大排序。
證明:按右端點升序排列可以得到最優值
把右端點從左向右排,使得右端點以後的區間能有更大的空間覆蓋。
比如現在有 \(5\) 條線段,如下:
---
-
----
-----
------
按右端點升序排序後:
-
---
----
------
-----
最優解為:
-
----
-----
如果按左端點升序排列,會發現什麼?會發現我給的樣例不好。
會發現答案還是一樣。
那麼如果把線段 \([1,3]\)
-
-----
----
------
-----
按這個形式的最優解就為:
-
-----
發現反例,所以得證。(偽證啊喂
程式碼
//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; }