알고리즘 아이디어..
글쓴이: Silvester / 작성시간: 월, 2011/11/21 - 4:21오전
대학생 경시대회 문제를 푸는 도중에 한 가지 문제에 봉착해서 궁금해서 올립니다.
Plane이 2개로 나뉘어지고 동시에 각 플레인에 점들이 모여 있습니다 (y축 기준으로 -x, x 에 각각 점이 몰려있다고 생각하시면 됨..)
각 plane을 disjoint set이라고 한다면 각 disjoint의 점에서 다른 disjoint 점을 연결해 길이를 구할 수 있는데, 이 때 전체 점에 대해서, |y2 - y1| + |x2 - x1| 의 최소 min을 구한다고 할 때, set이 한 개라면 그냥 binary search 응용해서 풀면 되겠다고 생각을 했는데, 2개 이상의 set에서 각 set을 연결하는 거리는 어떻게 binary search를 이용해서 풀어야할지 막막합니다.
아래에 한 개짜리에서 2개짜리로 만들다가 실패하고 있는데 혹시 조언을 해주실 수 있다면 감사하겠습니다.
예시, 힌트 어떤 것이라도 좋으니 부탁드립니다 ㅠㅠ
#include <iostream> #include <algorithm> #include <iomanip> #include <cmath> using namespace std; const int MAX = 10001; struct point{ int x,y; }; bool xCompare(struct point, struct point); bool yCompare(struct point, struct point); int dis(struct point, struct point); int absd(int); int trace(int,int,int,int); point p[MAX], q[MAX], tmp[MAX]; int main(){ int left; int right; scanf("%d\n", &left); memset(p,0,sizeof(p)); memset(q,0,sizeof(q)); memset(tmp,0,sizeof(tmp)); for(int i=0; i<left; i++){ cin >> p[i].x >> p[i].y; } scanf("%d\n", &right); for(int j=0; j<right; j++){ cin >> q[j].x >> q[j].y; } sort(p, p+left, xCompare); sort(q, q+right, xCompare); int min = trace(0,0, left-1, right-1); printf("%d\n", min); /** while(true){ cin >> n; if(n == 0) break; memset(p,0,sizeof(p)); memset(tmp,0,sizeof(tmp)); for(int i= 0;i<n;i++) cin >> p[i].x >> p[i].y; sort(p,p+n,xCompare); int min = trace(0,n-1); if(min < 10000 && n > 1){ cout << fixed; cout << setprecision(4) << min << endl; } else cout << "INFINITY" << endl; } **/ return 0; } int trace(int low1, int low2, int high1, int high2){ if(high1 - low1 < 3){ int value = dis(p[low1],q[low2+1]); int nextValue; if(high1 - low1 == 2){ nextValue = dis(p[low1],q[low2+2]); if(value > nextValue) value = nextValue; nextValue = dis(p[low1+1],q[low2+2]); if(value > nextValue) value = nextValue; } return value; } else{ /* DIVIDE & QONQUER */ int mid1 = (low1 + high1) >> 1; int mid2 = (low2 + high2) >> 1; int cnt = 0; int leftValue = trace(low1,low2,mid1,mid2); // left trace int rightValue = trace(mid1+1,mid2+1,high1,high2); // right trace // min value find int value = leftValue < rightValue ? leftValue : rightValue; /* Middle Condition Check : Y Line */ // saving left for(int i = low1;i<=mid1;i++){ if(abs(p[i].x - q[mid2].x) <= value) tmp[cnt++] = p[i]; } // saving right for(int i = mid1+1;i<=high1;i++){ if(absd(p[i].x - q[mid2+1].x) <= value) tmp[cnt++] = p[i]; } sort(tmp,tmp+cnt,yCompare); for(int i = 0;i<cnt;i++){ int count = 0; for(int j = i-3;count < 6 && j < cnt;j++){ if(j >= 0 && i != j){ int distance = dis(tmp[i],tmp[j]); if(value > distance) value = distance; count++; } } } return value; } } int absd(int x){ if( x < 0) return -x; return x; } int dis(struct point a, struct point b){ return (abs(a.x-b.x) + abs(a.y-b.y)); } bool xCompare(struct point a, struct point b){ return a.x < b.x; } bool yCompare(struct point a, struct point b){ return a.y < b.y; }
Forums:
2개에 대해서 구할 수 있으면 3개 이상에 대해서도,
2개에 대해서 구할 수 있으면 3개 이상에 대해서도, 예를 들어 A, B, C가 있을 때 A와 B를 구하고, B와 C를 구하고, A와 C를 구하면 되는거 아닌가요?
피할 수 있을때 즐겨라! http://melotopia.net/b
무슨 문제를 풀려고 하는지에 대한 설명을 제대로 하지
무슨 문제를 풀려고 하는지에 대한 설명을 제대로 하지 않은 상태에서 '요렇게 하면 이런 경우에 되는데 일반화가 안된다' 라고만 하셔서, 풀고자 하는 문제가 뭔지 알 수가 없지만,
아마도 k-d tree 같은걸 사용하면 되지 않을까 하는 생각이 듭니다.
음
Min-cost maximum flow인 듯 한데, 점의 개수가 1만이라면 대학생 프로그래밍 대회에서 책정된 시간 제한내에
들어올지 의문입니다. 다른 솔루션이 있을 듯 합니다.
댓글 달기