궁금한 부분은 이 부분입니다.
double lo = max(minX(a), minX(b));
double hi = min(maxX(a), maxX(b));
solve 함수 내에서 삼분탐색을 위해 가장 초기값을 잡는 부분이 위의 두 코드인데
문제의 목적은 다각형의 교차부분에 대한 길이를 찾는 것이니
교차하는 다각형에 대한 끝점들을 초기값으로 잡아야되는 것이 아닌가 하는 궁금증 입니다.
저 두 코드로 초기값을 잡게되면 교차점의 끝점보다 더 왼쪽이나 오른쪽에 있는 x좌표가 초기값으로 잡힐 수 있고,
이렇게 되면 삼분탐색 과정간에서 교차하는 부분을 탐색하게 될 수도 있지만 교차안하는 부분을 탐색할 수도 있는 것 아닌가 싶어서 질문드립니다.
이에 대해 제가 생각해본 부분은
교차 안하는 부분을 탐색하게 되면 vertical 함수로 구해지는 길이가 음수로 반환이 되니 더 큰 값을 찾아 삼분탐색을 하게되면서 자연스럽게 교차하는 부분을 찾아가게되니 문제없는 것 같기도 하고..
제 생각한 부분이 얼추 맞는건지 아니면 저렇게 사용하는 정확한 이유가 궁금합니다.
질문을 위해서 아래에 코드를 첨부해놓겠습니다.
#include <iostream>#include <vector>#include <queue>#include <stack>#include <algorithm>#include <set>#include <cmath>#include <limits>usingnamespacestd;structpoint{doublex,y;};typedefvector<pair<point,point>>vp;voiddecompose(vp&upper,vp&lower,vector<point>&a){intn=a.size();for(inti=0;i<n;i++){if(a[i].x<a[(i+1)%n].x){lower.push_back({a[i],a[(i+1)%n]});}else{upper.push_back({a[i],a[(i+1)%n]});}}}doubleminX(vector<point>&a){doubleans=1e9;for(inti=0;i<a.size();i++){ans=min(ans,a[i].x);}returnans;}doublemaxX(vector<point>&a){doubleans=-1;for(inti=0;i<a.size();i++){ans=max(ans,a[i].x);}returnans;}boolbetween(pair<point,point>&line,doublex){return(line.first.x<=x&&x<=line.second.x)||(line.second.x<=x&&x<=line.first.x);}doublecalY(point&a,point&b,doublex){// 직선의 방정식// y = m(x-x1)+y1return(b.y-a.y)/(b.x-a.x)*(x-a.x)+a.y;}// 주어진 x좌표에 대해서 껍질들의 y좌표를 확인하여 그 차액(길이)를 리턴한다.doublelen(vp&upper,vp&lower,doublex){doubleminY,maxY;minY=1e9,maxY=-1;// 위껍질의 선분들을 확인하여 주어진 x와 겹치는 y의 최솟값을 찾는다for(inti=0;i<upper.size();i++){// 위껍질의 선분이 현재 x점의 수직선과 마주치는지 확인한다if(between(upper[i],x)){// 만약 마주친다면(겹쳐진다면) 직선의 방정식 공식을 이용하여 x에 대한 y점을 가져온다.minY=min(minY,calY(upper[i].first,upper[i].second,x));}}// 아래껍질의 선분들을 확인하여 주어진 x와 겹치는 y의 최댓값을 찾는다for(inti=0;i<lower.size();i++){// 위껍질의 선분이 현재 x점의 수직선과 마주치는지 확인한다if(between(lower[i],x)){// 만약 마주친다면(겹쳐진다면) 직선의 방정식 공식을 이용하여 x에 대한 y점을 가져온다.maxY=max(maxY,calY(lower[i].first,lower[i].second,x));}}// 길이를 반환한다returnminY-maxY;}doublesolve(vp&upper,vp&lower,vector<point>&a,vector<point>&b){doublelo=max(minX(a),minX(b));doublehi=min(maxX(a),maxX(b));// 겹치지 않는 경우if(hi<lo)return0;for(inti=0;i<100;i++){doublelp=(2*lo+hi)/3;doublerp=(lo+2*hi)/3;if(len(upper,lower,lp)<len(upper,lower,rp))lo=lp;elsehi=rp;}// 경우에 따라 교집합의 길이가 아닌 부분이 반환될 수 있으니 (음수) 조건을 주어서 반환한다returnmax(0.0,len(upper,lower,hi));}intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);intT;cin>>T;while(T--){intn,m;cin>>n>>m;vector<point>poly1,poly2;for(inti=0;i<n;i++){pointa;cin>>a.x>>a.y;poly1.push_back(a);}for(inti=0;i<m;i++){pointa;cin>>a.x>>a.y;poly2.push_back(a);}// 아래, 위 껍질을 구분해준다// 껍질의 구분으로 받게 될 값들은 "선분" 이 기준이 된다vpupper,lower;decompose(upper,lower,poly1);decompose(upper,lower,poly2);// 껍질을 구분했으면 삼분탐색을 통해 문제를 해결한다cout<<fixed;cout.precision(10);cout<<solve(upper,lower,poly1,poly2)<<"\n";}return0;}
junnnho
궁금한 부분은 이 부분입니다.
double lo = max(minX(a), minX(b));
double hi = min(maxX(a), maxX(b));
solve 함수 내에서 삼분탐색을 위해 가장 초기값을 잡는 부분이 위의 두 코드인데
문제의 목적은 다각형의 교차부분에 대한 길이를 찾는 것이니
교차하는 다각형에 대한 끝점들을 초기값으로 잡아야되는 것이 아닌가 하는 궁금증 입니다.
저 두 코드로 초기값을 잡게되면 교차점의 끝점보다 더 왼쪽이나 오른쪽에 있는 x좌표가 초기값으로 잡힐 수 있고,
이렇게 되면 삼분탐색 과정간에서 교차하는 부분을 탐색하게 될 수도 있지만 교차안하는 부분을 탐색할 수도 있는 것 아닌가 싶어서 질문드립니다.
이에 대해 제가 생각해본 부분은
교차 안하는 부분을 탐색하게 되면 vertical 함수로 구해지는 길이가 음수로 반환이 되니 더 큰 값을 찾아 삼분탐색을 하게되면서 자연스럽게 교차하는 부분을 찾아가게되니 문제없는 것 같기도 하고..
제 생각한 부분이 얼추 맞는건지 아니면 저렇게 사용하는 정확한 이유가 궁금합니다.
질문을 위해서 아래에 코드를 첨부해놓겠습니다.
4년 전