其实lyd书上的题目,在贪心那一张有,解法就不放了自己看。
个人觉得主要难点or瓶颈在于把覆盖问题化为区间选点问题,每个点对应一个能覆盖到他的区间。这个怎么说呢。。反正想到了就想到了,想不到就是想不到,也没什么说的。。。希望对其他题有借鉴价值(不过哪个**出题人还会出这种转化啊)。
然后就是区间上最少点覆盖。贪心,看lyd书去。只能大概感性认识一下,lyd给的证明貌似没什么道理,大概是分两点:1.在可以用已有机器管辖也可以新建一台机器管辖的时候选前者,因为后者可以放到以后再选更优;2.选前者时保证当前机器管得住所有点同时尽量往右移。
真心不太会这种贪心,老是想不到,哎,我还是太菜了呢。
顺带记一下多个区间选其中若干互不重叠的区间,求最多选多少个。这个是我希望线段结束的越早越好,所以以结束点从小到大排,不断去选。感觉这些只可意会的说。。
Upd:区间最少点覆盖和最少不相交区间的答案是不是一样的?我尝试证明了一下,发现证的不太严谨,感觉是对的。。虽然很好写,但是现在不是很想对拍。。所以这个试验就先鸽了。
WA记录:我也不知道为什么WA,改到最后是line35的if出错,但是原来写的是判断平方差是否<0,好像也对啊,我也不知道怎么回事。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define dbg(x) cerr<<#x<<" = "<<x<<endl 7 #define ddbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl 8 using namespace std; 9 typedef pair<int,int> pii; 10 typedef double db; 11 typedef long long ll; 12 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 13 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 14 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 15 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 16 template<typename T>inline T read(T&x){ 17 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 18 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 19 } 20 const int N=1000+7; 21 const db eps=1e-4; 22 struct kokubyakuin_seira{ 23 db l,r; 24 inline bool operator <(const kokubyakuin_seira&B)const{return l<B.l;} 25 }A[N]; 26 db x,y,d,pos; 27 int n,ans,T,yuuouji_ouka; 28 29 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout); 30 read(n),read(d); 31 while(n||d){ 32 yuuouji_ouka=0; 33 for(register int i=1;i<=n;++i){ 34 read(x),read(y); 35 if(d-y<0)yuuouji_ouka=1; 36 else A[i].l=x-sqrt(d*d-y*y),A[i].r=x+sqrt(d*d-y*y); 37 } 38 if(yuuouji_ouka){printf("Case %d: -1 ",++T);read(n),read(d);continue;} 39 sort(A+1,A+n+1);pos=A[1].r,ans=1; 40 for(register int i=2;i<=n;++i)A[i].l>pos?(++ans,pos=A[i].r):MIN(pos,A[i].r); 41 printf("Case %d: %d ",++T,ans); 42 read(n),read(d); 43 } 44 return 0; 45 }