Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- inline double dist2(point a, point b){ return (a.first - b.first)*(a.first - b.first) + (a.second - b.second)*(a.second - b.second);}
- inline point toVec(point a, point b){ return point(b.first-a.first,b.second-a.second); }
- inline double dot(point a, point b){ return a.first *b.first + a.second * b.second; }
- inline double norm_sq(point v){ return v.first*v.first + v.second * v.second;}
- inline double distToLine(point p, point a, point b){
- point c;
- point ap = toVec(a, p), ab = toVec(a, b);
- double u = dot(ap,ab) / (double)norm_sq(ab);
- c.first = (double)a.first + ab.first*u;
- c.second = (double)a.second + ab.second*u;
- return sqrt(dist2(a,c));
- }
- inline double orientation(point p, point q, point r){
- return (q.second - p.second) * (r.first - p.first) - (q.first - p.first) * (r.second - p.second);
- }
- void convexHull(){ // Andrew's Monotone Chain Algorithm
- up.assign(n,point()); dn.assign(n,point());
- int i = 0, j = 0;
- for(int k = 0; k < n; k++){
- while(i > 1 && orientation(up[i-2], up[i-1], pts[k]) <= 0) i--;
- while(j > 1 && orientation(dn[j-2], dn[j-1], pts[k]) >= 0) j--;
- up[i++] = pts[k];
- dn[j++] = pts[k];
- }
- chPts.assign(i+j-2,point());
- for(int k = 0; k < j; k++) chPts[k] = dn[k];
- for(int k = i-2, l = j; k > 0; k--, l++) chPts[l] = up[k];
- }
- inline int nxt(int id){ return (id+1)%chPts.size(); }
- inline int prev(int id){ return (id == 0 ? (int)chPts.size() : id) - 1;}
- void rotatingCalipers(){
- int maxX=0,minX=0,minY=0,maxY=0;
- for(int i = 1; i < n; i++){ // extremos
- if(chPts[maxX].first < chPts[i].first) maxX = i;
- if(chPts[minX].first > chPts[i].first) minX = i;
- if(chPts[maxY].second < chPts[i].second) maxY = i;
- if(chPts[minY].second > chPts[i].second) minY = i;
- }
- int p[4] = {minX, minY, maxX, maxY}, p0[4];
- for(int i = 0; i < 4; i++){
- p0[i] = prev(p[(i + 2)%4]);
- }
- double ansAr = 1e8, ansPer = 1e8, l1, l2;
- while(1){
- bool ok = false;
- for(int i = 0; i < 4; i++) if(p[i] != p0[i]){ ok = true; break;}
- if(!ok)break;
- int incr = -1, ia, ib, ic, id, ie;
- for(int i = 0; i < 4; i++){
- if(p[i] == p0[i]) continue;
- if(incr == -1) incr = i;
- else{
- if((chPts[nxt(p[i])].second - chPts[p[i]].second) * (chPts[p[incr]].first - chPts[nxt(p[incr])].first )
- > (chPts[p[incr]].second - chPts[nxt(p[incr])].second) * (chPts[nxt(p[i])].first - chPts[p[i]].first))
- incr = i;
- }
- }
- // ia e ib: line segment AB
- ia = p[incr];
- ib = p[incr] = nxt(p[incr]);
- // ic e id: points that touch the sides orthogonal to AB
- ic = p[(incr == 0 ? 4 : incr)-1];
- id = p[(incr+1)%4];
- // ie: opposite to the segment
- ie = p[(incr+2)%4];
- l1 = distToLine(chPts[ie],chPts[ia],chPts[ib]);
- point ab = toVec(chPts[ia], chPts[ib]), cd = toVec(chPts[ic], chPts[id]);
- // Projection of CD on AB
- l2 = fabs(dot(ab,cd) / (double)norm_sq(ab));
- ansAr = min(ansAr, l1*l2);
- ansPer = min(ansPer,2*(l1+l2));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement