1. 程式人生 > >Codeforces 780 H Intranet of Buses

Codeforces 780 H Intranet of Buses

在這裡插入圖片描述在這裡插入圖片描述毒瘤出題人A了一道毒瘤題然後搬。。。。。。
思路很簡單,二分答案後two-pointers把每對邊,相鄰的鴿子會各自在其上的情況求距離小於二分的答案的時間區間,這是個二次函式直接求。然後發現判定答案就是找交集。轉化為非法區間取並就可以排序貪心判定合法。

這題讓我深刻的理解到計算幾何題好像是過了樣例就能A,在打完後完全不相信自己能A的蒟蒻如是說。

#include<bits/stdc++.h>
#define maxn 200005
#define eps 1e-7
using namespace std;

inline int dcmp(double a)
{
	if(
fabs(a) < 1e-7) return 0; return a>0?1:-1; } int n,m,npt; double len[maxn],arrtim[maxn]; inline double sqr(double x){ return x*x; } struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y){} Point operator +(const Point &B)const{ return Point(x+B.x,y+B.y); } Point operator -(const
Point &B)const{ return Point(x-B.x,y-B.y); } Point operator *(const double B)const{ return Point(x*B,y*B); } double Len(){ return sqrt(sqr(x)+sqr(y)); } }st,P[maxn],dir[maxn]; double dist(Point A,Point B){ return (B-A).Len(); } double C; double tl[maxn*10],tr[maxn*10]; int ct[maxn*10],cnt_t; inline
bool cmp(const int &u,const int &v){ return tl[u] < tl[v]; } inline double diV(double t){ return floor(t / C); } inline double dmod(double t) { return t - C * floor(t / C); } bool ERROR = 0; void Insert(double s,double t) { if(dcmp(diV(t) - diV(s)) == 1) { if(dcmp(dmod(t) - dmod(s)) == 1 || dcmp(diV(t)-diV(s)-1) == 1) ERROR = 1; else { tl[++cnt_t] = dmod(s) , tr[cnt_t] = C; tl[++cnt_t] = 0 , tr[cnt_t] = dmod(t); } } else { tl[++cnt_t] = dmod(s) , tr[cnt_t] = dmod(t); } } inline bool check(double mid) { //printf("%lf\n",mid); double tnow=0; cnt_t = ERROR = 0; Point st1 = P[1] , st2 = st; for(int npt1=2,npt2=npt;npt1<=n+1 && npt2 <= npt + n;) { double lim1 = arrtim[npt1] , lim2 = arrtim[npt2] - C; // if(mid <=2) // printf("%d %d %lf %lf\n",npt1,npt2,lim1,lim2); /* (st1 + k * dir[npt1-1] - st2 - k * dir[npt2-1]).Len() <= mid ((st1.x-st2.x)+k(dir[npt1-1].x-dir[npt2-1].x))^2 + ((st1.y-st2.y)+k(dir[npt1-1].y-dir[npt2-1].y))^2 <= mid ^ 2 */ // if(mid>=1.02 && mid <= 1.04)printf("%d %d\n",npt1,npt2); // if(mid >= 1.02 && mid <= 1.04)printf("%lf %lf %lf %lf\n",st1.x,st1.y,st2.x,st2.y); double A1 = st1.x - st2.x , A2 = dir[npt1-1].x-dir[npt2-1].x; double B1 = st1.y - st2.y , B2 = dir[npt1-1].y-dir[npt2-1].y; // if(mid <= 0.9) printf("%lf %lf %lf %lf\n",A1,A2,B1,B2); double A = sqr(A2) + sqr(B2) , B = 2 * A1 * A2 + 2 * B1 * B2 , C = sqr(A1) + sqr(B1) - mid * mid; double delta = sqr(B) - 4 * A * C; // if(mid<=0.9) printf("%lf %lf %lf %lf\n",A,B,C,delta); // if(mid<=0.9)printf("%lf %lf %lf\n",tnow,lim1,lim2); if(dcmp(delta) == -1) Insert(tnow , min(lim1,lim2)); else { delta = sqrt(delta); if(dcmp(A) != 0) { double x1 = (-B-delta)/(2*A) , x2 = (-B+delta)/(2*A); // if(mid<= 0.9) // printf("%lf %lf\n",x1,x2); if(x1 > 0) Insert(tnow , min(min(lim1,lim2),tnow + x1)); if(x2+tnow < min(lim1,lim2)) Insert(max(x2+tnow,tnow),min(lim1,lim2)); } else if(dcmp(B) == 0) { if(C > 0) Insert(tnow,min(lim1,lim2)); } else if(dcmp(B) == 1) { double x = - C / B; Insert(max(tnow,tnow+x),min(lim1,lim2)); } else { double x = -C / B; Insert(tnow,min(min(lim1,lim2),tnow+x)); } } double tnxt = min(lim1,lim2); // if(mid>=1.02 && mid <= 1.04) // printf("%lf\n",tnxt); if(dcmp(lim1-tnxt)!=1) st1=P[npt1],npt1++; else st1 = st1 + dir[npt1-1] * (tnxt - tnow); if(dcmp(lim2-tnxt)!=1) st2=P[npt2],npt2++; else st2 = st2 + dir[npt2-1] * (tnxt - tnow); tnow = tnxt; } if(ERROR) return 0; double Max = eps; for(int i=1;i<=cnt_t;i++) ct[i] =i; sort(ct+1,ct+1+cnt_t,cmp); //if(mid >= 1.02 && mid <= 1.04) //{ // for(int i=1;i<=cnt_t;i++) // printf("%lf %lf\n",tl[ct[i]],tr[ct[i]]); //printf("\n"); //} for(int i=1;i<=cnt_t;i++) { if(dcmp(tl[ct[i]]-Max) == 1) { return 1; } Max = max(Max , tr[ct[i]]); } if(dcmp(Max-C) == -1) return 1; return 0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lf%lf",&P[i].x,&P[i].y); P[n+1] = P[1]; for(int i=1;i<=n;i++) len[i] = dist(P[i],P[i+1]) , C+=len[i] , arrtim[i+1] = C, dir[i] = (P[i+1] - P[i])*(1/(P[i+1]-P[i]).Len()); for(int i=1;i<=n;i++) arrtim[n+i+1] = C + arrtim[i+1], dir[i+n] = dir[i], P[i+n] = P[i] , len[i+n] = len[i]; C /= m; int id = 1; double sel = C; for(;dcmp(len[id]-sel)!=1;id++) sel-=len[id]; id = (id-1) + 1; st = P[id] + dir[id] * sel; npt = id + 1; double l = 0 , r = 10000 , mid; for(;r-l>eps;) { mid = (l+r) * 0.5; if(check(mid)) r = mid; else l = mid + eps; } printf("%.7lf",l); }