본문 바로가기

ps(알고리즘)

선분 그룹

 

이 문제는 왜 플레에 있는지 모르겠을 정도로 간단한데, 그냥 선분교차에 대한 처리 방법만 알면 된다.

선분이 교차한다는 것은 한 선분을 기준으로, 나머지 선분의 두 점이 각각 다른 방향에 존재하는 것이다.

여기서 방향은 전에 풀었던 convex-hull 에서 배웠던 ccw 함수를 쓰면 된다.

그런데 방향이 달라도 직선이 아니라 선분이기 때문에 교차하지 않을 수 있다.

따라서 한 선분만 기준으로 검사하는 것이 아니라, 각 선분을 기준으로 삼아서 검사를 두번 진행해야 한다.

그리고 한가지 경우를 더 처리해야 하는데, 두 선분의 점 4개가 모두 일직선에 있을 경우이다.

이 때는 한 선분의 max 꼭짓점이 다른 선분의 min꼭짓점보다 크기만 하면 교차한다.

 

이렇게 교차 여부 검사 함수만 짜면, 나머지는 그냥 이중for문을 돌면서 교차하면 union-find로 그룹지어주면 끝이다.

#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
int N;
int parent[3004];
int groups[3004];
struct Data
{
    pair<int,int> a,b;
}line[3004];
int ccw(pair<int,int>a, pair<int,int>b, pair<int,int>c)
{
    pair<int,int>ab = make_pair(b.first-a.first,b.second-a.second);
    pair<int,int>ac = make_pair(c.first-a.first,c.second-a.second);
    if(ab.first*ac.second - ab.second*ac.first>0) return 1;
    else if(ab.first*ac.second - ab.second*ac.first<0) return -1;
    else return 0;
}
bool check(pair<int,int>a, pair<int,int>b, pair<int,int>c, pair<int,int>d)
{
    if(ccw(a,b,c)*ccw(a,b,d)==0 && ccw(c,d,a)*ccw(c,d,b)==0)
    {
        if(max(a,b)>=min(c,d) && min(a,b)<=max(c,d)) return true;
        else return false;
    }
    if(ccw(a,b,c)*ccw(a,b,d)<=0 && ccw(c,d,a)*ccw(c,d,b)<=0) return true;
    else return false;
}
int finds(int a)
{
    if(a==parent[a]) return a;
    return parent[a] = finds(parent[a]);
}
void unions(int a, int b)
{
    if(finds(a)!=finds(b))
    {
        parent[finds(a)] = finds(b);
    }
}
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        int a,b,c,d;
        scanf("%d %d %d %d",&a,&b,&c,&d);
        line[i]={make_pair(a,b),make_pair(c,d)};
    }
    for(int i=1;i<=N;i++) parent[i]=i;
    for(int i=1;i<N;i++)
    {
        for(int j=i+1;j<=N;j++)
        {
            if(check(line[i].a,line[i].b,line[j].a,line[j].b))
            {
                unions(i,j);
            }
        }
    }
    for(int i=1;i<=N;i++)
    {
        groups[finds(i)]++;
    }
    int groupnum=0,maxgroup=0;
    for(int i=1;i<=N;i++)
    {
        if(groups[i]!=0)
        {
            groupnum++;
            if(maxgroup<groups[i]) maxgroup = groups[i];
        }
    }
    printf("%d\n%d",groupnum,maxgroup);
}

구현 코드이다.

'ps(알고리즘)' 카테고리의 다른 글

사탕상자  (0) 2024.12.04
전깃줄-2  (0) 2024.12.03
볼록 껍질  (0) 2024.12.03
Strongly Connected Componen  (0) 2024.12.03
백조의 호수  (0) 2024.11.28