상세 컨텐츠

본문 제목

CLASS 6 - P4

알고리즘/solved.ac - CLASS

by oVeron 2024. 6. 8. 14:38

본문

728x90
반응형

1014번: 컨닝 - DP(비트마스킹)

/*
입력된 판을 열을 기준으로 보자. 특정 열의 한 자리에 책상을 놓을 경우, 좌우 열에만 영향을 줄 뿐
같은 열에는 영항을 주지 않음을 알 수 있다. 따라서 n번째 열에 책상을 놓는 경우는 n-1번째 열에만
영향을 받는다. 이때 n~M번째 열에 책상을 놓는 경우는 n+1~M번째 열에 책상을 놓는 경우를 통해 알아
낼 수 있다. 즉 작은 문제를 해결함으로써 그 결과로 큰 문제를 해결할 수 있으므로, 이 문제는 DP로
해결할 수 있다. 각 열에 의자를 놓는 경우의 수는 비트마스크를 이용해 관리하면 된다.
*/

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

int N, M;
char classroom[11][11];
int dp[10][1024]; //dp[c][s] : c-1번째 열에 책상 집합 s를 배치할 경우의 최댓값

int DP(int c, int s)
{
    if(c == M) return 0;
    if(dp[c][s] != -1) return dp[c][s];
    
    dp[c][s] = 0;
    for(int i=0; i<(1 << N); i++)
    {
        int cnt = 0; //c번째 열에 놓는 책상의 수
        bool chk = true;
        for(int j=0; j<N; j++)
        {
            if(i & (1 << j))
            {
                cnt++;
                if(classroom[j][c] == 'x') chk = false; 
                //책상을 못 놓게 되어 있는 칸과 겹치면 안 된다.
            }
        }
        if(!chk) continue;
        
        bool noCheat[10] = {}; //집합 i처럼 책상을 놓을 경우 다음 열에 놓지 못하는 자리 배열
        char defDest[10]; //입력받은 기존의 다음 열 자리 배열
        for(int j=0; j<N; j++)
        {
            defDest[j] = classroom[j][c+1];
            if(i & (1 << j))
            {
                for(int k=j-1; k<=j+1; k++)
                {
                    if(k >= 0 && k < N) 
                        noCheat[k] = true;
                }
            }
        }
        
        for(int j=0; j<N; j++)
            if(noCheat[j]) classroom[j][c+1] = 'x'; //책상을 놓지 못하는 자리를 전처리
        dp[c][s] = max(dp[c][s], DP(c+1, i) + cnt);
        for(int j=0; j<N; j++) //복구
            classroom[j][c+1] = defDest[j];
    }
    return dp[c][s];
}

void solve()
{
    cin >> N >> M;
    for(int i=0; i<N; i++)
        for(int j=0; j<M; j++)
            cin >> classroom[i][j];
    
    memset(dp, -1, sizeof(dp));
    cout << DP(0, 0) << "\n";
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	int C; cin >> C;
	for(int i=1; i<=C; i++) solve();
}

 

2618번: 경찰차 - DP

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

int N, W;
pii event[1001];
int dp[1001][1001]; //dp[i][j] : 경찰차 1이 사건 i, 경찰차 2가 사건 j에 있을 때의 최단 경로
pii track[1001][1001];

int solve(int i, int j, int n)
{
    if(n == W+1) return 0;
    if(dp[i][j] != -1) return dp[i][j];
    
    int xi, yi, xj, yj;
    if(i == 0) xi = 1, yi = 1;
    else xi = event[i].first, yi = event[i].second;
    if(j == 0) xj = N, yj = N;
    else xj = event[j].first, yj = event[j].second;
    auto [xn, yn] = event[n];
    
    int ni = abs(xi-xn) + abs(yi-yn);
    int nj = abs(xj-xn) + abs(yj-yn);
    
    int reti = solve(n, j, n+1) + ni;
    int retj = solve(i, n, n+1) + nj;
    if(reti < retj) track[i][j] = {n, j};
    else track[i][j] = {i, n};
    
    return dp[i][j] = min(reti, retj);
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	cin >> N >> W;
	for(int i=1; i<=W; i++)
	{
	    int x, y; cin >> x >> y;
	    event[i] = {x, y};
	}
	
	memset(dp, -1, sizeof(dp));
	cout << solve(0, 0, 1) << "\n";
	
	int i = 0, j  = 0;
	for(int w=1; w<=W; w++)
	{
	    auto [ni, nj] = track[i][j];
	    if(nj == j) cout << 1 << "\n";
	    else cout << 2 << "\n";
	    i = ni, j = nj;
	}
}

 

3176번: 도로 네트워크 - LCA

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

int N, K;
vector<pll> graph[100001];
int height[100001];
int par[18][100001]; //부모 희소 배열
ll mn[18][100001], mx[18][100001]; //최소, 최대 희소 배열

void DFS(int u, int p, int h, ll dist)
{
    par[0][u] = p, height[u] = h;
    mn[0][u] = mx[0][u] = dist; //정점 u와 u의 부모와 연결된 간선을 저장
    
    for(auto [d, v] : graph[u])
    {
        if(v == p) continue;
        DFS(v, u, h+1, d);
    }
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
    cin >> N;
    for(int i=1; i<N; i++)
    {
        ll A, B, C; cin >> A >> B >> C;
        graph[A].push_back({C, B});
        graph[B].push_back({C, A});
    }
    
    DFS(1, 0, 0, 1e18);
    mx[0][1] = 0; //최대 희소 배열에서 정점 1(root)에 연결된 가상의 간선을 0으로 설정
    
    for(int i=1; i<18; i++)
    {
        for(int j=1; j<=N; j++)
        {
            par[i][j] = par[i-1][par[i-1][j]];
            mn[i][j] = min(mn[i-1][j], mn[i-1][par[i-1][j]]);
            //f(n)(x) = min(f(n-1)(x), d)와 같은 형태이다. 
            //따라서 거리의 최솟값에 대한 희소 배열을 만들 수 있다.
            mx[i][j] = max(mx[i-1][j], mx[i-1][par[i-1][j]]);
            //마찬가지로 거리의 최댓값에 대한 희소 배열도 만들 수 있다.
        }
    }
    
    cin >> K;
    for(int i=1; i<=K; i++)
    {
        int u, v; cin >> u >> v;
        if(height[u] > height[v]) swap(u, v);
        
        ll mn1 = 1e18, mn2 = 1e18;
        ll mx1 = 0, mx2 = 0;
        int d = height[v] - height[u];
        for(int j=0; j<18; j++)
        {
            if(d & (1 << j))
            {
                mn2 = min(mn2, mn[j][v]); mx2 = max(mx2, mx[j][v]);
                v = par[j][v];
            }
        }
        
        if(u != v)
        {
            for(int j=17; j>=0; j--)
            {
                if(par[j][u] != par[j][v])
                {
                    mn1 = min(mn1, mn[j][u]); mx1 = max(mx1, mx[j][u]);
                    mn2 = min(mn2, mn[j][v]); mx2 = max(mx2, mx[j][v]);
                    u = par[j][u], v = par[j][v];
                }
            }
            mn1 = min(mn1, mn[0][u]); mx1 = max(mx1, mx[0][u]);
            mn2 = min(mn2, mn[0][v]); mx2 = max(mx2, mx[0][v]);
        }
        
        cout << min(mn1, mn2) << " " << max(mx1, mx2) << "\n";
    }
}

 

3653번: 영화 수집 - 세그먼트 트리

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

int pn;
int segTree[800001];
int loc[100001]; //loc[i] : DVD의 번호가 i일 때 그 위치

void update(int idx, int n)
{
    idx += pn;
    segTree[idx] = n;
    
    for(idx/=2; idx>=1; idx/=2)
        segTree[idx] = segTree[idx*2] + segTree[idx*2+1];
}

int sum(int l, int r)
{
    l += pn, r += pn;
    int ret = 0;
    while(l <= r)
    {
        if(l%2 == 1) ret += segTree[l++];
        if(r%2 == 0) ret += segTree[r--];
        
        l /= 2, r /= 2;
    }
    return ret;
}

void solve()
{
    memset(segTree, 0, sizeof(segTree));
    int n, m; cin >> n >> m;
    
    pn = 1;
    while(pn < n+m) pn *= 2; //범위 주의
    
    //DVD의 존재를 0, 1로 표현해 세그먼트 트리로 누적합 관리
    for(int i=1; i<=n; i++) 
    {
        loc[i] = n-i;
        update(i-1, 1); 
    }
    
    for(int i=n; i<n+m; i++)
    {
        int dvd; cin >> dvd;
        cout << sum(loc[dvd]+1, i-1) << " ";
        
        update(loc[dvd], 0);
        loc[dvd] = i;
        update(loc[dvd], 1);
    }
    cout << "\n";
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	int T; cin >> T;
	while(T--) solve();
}

 

3679번: 단순 다각형 - 기하(CCW)

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;
typedef complex<int> coord;

#define X real()
#define Y imag()
int n;
vector<tiii> point;

coord p2v(coord p1, coord p2) { return {p2.X-p1.X, p2.Y-p1.Y}; }
int CCW(coord v1, coord v2) { return (conj(v1)*v2).Y; }

auto cmp = [](tiii t1, tiii t2)
{
    coord p0 = {get<0>(point[0]), get<1>(point[0])};
    coord p1 = {get<0>(t1), get<1>(t1)};
    coord p2 = {get<0>(t2), get<1>(t2)};
    coord v1 = p2v(p0, p1);
    coord v2 = p2v(p0, p2);
    
    int ccw = CCW(v1, v2);
    if(ccw > 0) return true;
    else if(ccw < 0) return false;
    else
    {
        if(v1.X*v1.X+v1.Y*v1.Y < v2.X*v2.X+v2.Y*v2.Y) return true;
        else return false;
    }
};

void solve()
{
    cin >> n;
    //x좌표가 가장 작은 점을 기준으로 CCW 정렬 -> 정렬한 점을 순서대로 출력하면 단순 다각형이 된다.
    for(int i=0; i<n; i++) 
    {
        int x, y; cin >> x >> y;
        point.push_back({x, y, i});
        auto [x0, y0, idx0] = point[0];
        auto [xi, yi, idxi] = point[i];
        if(xi < x0 || xi == x0 && yi < y0) swap(point[i], point[0]);
    }
    sort(point.begin() + 1, point.end(), cmp);
    
    //단, 단순 다각형에서 마지막으로 만든 변에 여러 개의 점이 있을 경우, 역순으로 출력해야 한다.
    int idx = n-1;
    while(true)
    {
        coord p0 = {get<0>(point[0]), get<1>(point[0])};
        coord p1 = {get<0>(point[idx]), get<1>(point[idx])};
        coord p2 = {get<0>(point[idx-1]), get<1>(point[idx-1])};
        coord v1 = p2v(p0, p1);
        coord v2 = p2v(p0, p2);
        
        int ccw = CCW(v1, v2);
        idx--;
        if(ccw != 0) break;
    }
    
    for(int i=0; i<=idx; i++)
    {
        auto [x, y, index] = point[i];
        cout << index << " ";
    }
    for(int i=n-1; i>idx; i--)
    {
        auto [x, y, index] = point[i];
        cout << index << " ";
    }
    cout << "\n";
    
    point.clear();
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	int c; cin >> c;
	while(c--) solve();
}

 

5670번: 휴대폰 자판 - 트라이

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

int N;
string word[100001];
int trie[1000001][26];
bool exist[1000001]; //이 노드까지 도달했을 때 단어가 완성되는지 확인
int childCnt[1000001]; //현재 노드의 자식의 수

int solve(int curNode, int w, int idx)
{
    if(word[w].size() == idx) return 0;
    
    int ret = 0;
    if(trie[curNode][word[w][idx]-'a'] != -1) 
        ret = solve(trie[curNode][word[w][idx]-'a'], w, idx+1);
    
    if(childCnt[curNode] == 1)
    {
        if(curNode == 0 || exist[curNode]) return ret + 1;
        else return ret;
    }
    else return ret + 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	while(cin >> N)
	{
	    memset(trie, -1, sizeof(trie));
	    memset(exist, false, sizeof(exist));
	    memset(childCnt, 0, sizeof(childCnt));
	    
	    int node = 1;
	    for(int i=1; i<=N; i++)
	    {
	        cin >> word[i];
	        int curNode = 0;
	        for(int j=0; j<word[i].size(); j++)
	        {
	            if(trie[curNode][word[i][j]-'a'] == -1)
	            {
	                childCnt[curNode]++;
	                curNode = trie[curNode][word[i][j]-'a'] = node++;
	            }
	            else curNode = trie[curNode][word[i][j]-'a'];
	        }
	        exist[curNode] = true;
	    }
	    
	    int ans = 0;
	    for(int i=1; i<=N; i++) ans += solve(0, i, 0);
	    cout << fixed << setprecision(2) << double(ans) / N << "\n";
	}
}

 

11266번: 단절점 - 그래프(DFS 스패닝 트리, BCC)

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

int V, E;
vector<int> graph[10001];
int DFS_num[10001], DFS_min[10001];
int DFS_cnt = 1;
stack<pii> edge;
bool candi[10001], root[10001];
int childCnt[10001];

void DFS(int u, int p) //u : 정점, p : 정점의 부모
{
    DFS_num[u] = DFS_min[u] = DFS_cnt++;
    for(int v : graph[u])
    {
        if(v == p) continue; //부모를 만나면 무시
        
        if(DFS_num[v]) DFS_min[u] = min(DFS_min[u], DFS_num[v]);
        //이미 방문한 정점을 만났다면(역방향 간선), 해당 정점이 만날 수 있는 정점의 최솟값 갱신
        //DFS_min[v]를 쓰면 다른 BCC에 v가 포함되니 주의
        else
        {
            DFS(v, u); //방문하지 않은 정점을 만났다면(트리 간선), 계속 DFS
            DFS_min[u] = min(DFS_min[u], DFS_min[v]); //최솟값 갱신. 이번에는 DFS_min[v]를 사용
            if(DFS_num[u] <= DFS_min[v]) candi[u] = true;
            //해당 노드의 자식들이 해당 노드의 선조를 만나지 않았다면, 이 노드는 단절점의 후보군이 될 수 있다.
            childCnt[u]++; //노드의 자식 수 세기. 트리 간선 수만 세면 된다.
        }
    }
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	cin >> V >> E;
	for(int i=1; i<=E; i++)
	{
	    int A, B; cin >> A >> B;
	    graph[A].push_back(B);
	    graph[B].push_back(A);
	}
	
	for(int i=1; i<=V; i++) //연결 그래프가 아닐 수 있으므로 모든 정점에 대해 DFS
	{
	    if(!DFS_num[i]) 
	    {
	        root[i] = true; //처음 방문한 정점을 루트 처리
	        DFS(i, 0);
	    }
	}
	
	vector<int> ans;
	for(int i=1; i<=V; i++)
	    if(candi[i] && (!root[i] || childCnt[i] >= 2)) //트리의 루트라면 자식의 수가 2개 이상이어야 한다.
	        ans.push_back(i);
	
	cout << ans.size() << "\n";
	for(int i : ans) cout << i << " ";
}

 

11280번: 2-SAT - 3 - SCC(2-SAT)

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

const int SIZE = 20001;
int N, M;
vector<int> graphf[SIZE], graphr[SIZE];
bool vis[SIZE];
stack<int> st;
vector<vector<int>> SCC;
int SCCIdx[SIZE];

int tog(int n) //n을 not n으로 toggle
{
    if(n <= N) return n + N;
    else return n - N;
}

void DFSf(int u)
{
    vis[u] = true;
    for(int v : graphf[u])
        if(!vis[v]) DFSf(v);
    st.push(u);
}

void DFSr(int u)
{
    vis[u] = true;
    SCC.back().push_back(u);
    SCCIdx[u] = SCC.size() - 1; //정점 u가 SCC의 어느 index에 위치하는지 저장
    
    for(int v : graphr[u])
        if(!vis[v]) DFSr(v);
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	cin >> N >> M;
	for(int i=1; i<=M; i++)
	{
	    int u, v; cin >> u >> v;
	    if(u < 0) u = -u + N;
	    if(v < 0) v = -v + N;
	    
	    graphf[tog(u)].push_back(v); //not u -> v
	    graphf[tog(v)].push_back(u); //not v -> u
	    graphr[v].push_back(tog(u));
	    graphr[u].push_back(tog(v));
	}
	
	for(int i=1; i<=N*2; i++)
	    if(!vis[i]) DFSf(i);
	    
	memset(vis, false, sizeof(vis));
	while(!st.empty())
	{
	    int u = st.top(); st.pop();
	    if(!vis[u])
	    {
	        SCC.emplace_back();
	        DFSr(u);
	    }
	} //코사라주 알고리즘
	
	bool canSCC = true;
	for(int i=1; i<=N; i++)
	{
	    if(SCCIdx[i] == SCCIdx[tog(i)]) //i와 not i가 한 SCC에 있을 수는 없다.
	        canSCC = false;
	}
	
	if(!canSCC) cout << 0;
	else cout << 1;
}

 

11400번: 단절선 - 그래프(DFS 스패닝 트리, BCC)

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

const int SIZE = 100001;
int V, E;
vector<int> graph[SIZE];
int DFS_num[SIZE], DFS_min[SIZE];
int DFS_cnt = 1;
vector<pii> edge;

void DFS(int u, int p)
{
    DFS_num[u] = DFS_min[u] = DFS_cnt++;
    for(int v : graph[u])
    {
        if(v == p) continue;
        
        if(DFS_num[v]) DFS_min[u] = min(DFS_min[u], DFS_num[v]);
        else
        {
            DFS(v, u);
            DFS_min[u] = min(DFS_min[u], DFS_min[v]);
            if(DFS_num[u] < DFS_min[v]) 
            //본래의 BCC 알고리즘에서 이 둘이 같을 때는 역방향 간선이 존재할 때 뿐이다.
            //역방향 간선이 존재하지 않는다면, (u, v)는 단절선이 된다.
            {
                int U = u, V = v;
                if(U > V) swap(U, V);
                edge.push_back({U, V});
            }
        }
    }
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	cin >> V >> E;
	for(int i=1; i<=E; i++)
	{
	    int A, B; cin >> A >> B;
	    graph[A].push_back(B);
	    graph[B].push_back(A);
	}
	
	DFS(1, 0);
	
	sort(edge.begin(), edge.end());
	cout << edge.size() << "\n";
	for(auto [u, v] : edge)
        cout << u << " " << v << "\n";
}

 

14939번: 불 끄기 - 완전 탐색

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;

bool board[10][10];
bool newboard[10][10];
int dir[2][4] = {{-1, 1, 0, 0}, {0, 0, -1, 1}};
int cnt = 0;
int ans = -1;

void bulb(int x, int y)
{
    newboard[x][y] = !newboard[x][y];
    for(int i=0; i<4; i++)
    {
        int nx = x + dir[0][i];
        int ny = y + dir[1][i];
        
        if(nx >= 0 && nx < 10 && ny >= 0 && ny < 10)
            newboard[nx][ny] = !newboard[nx][ny];
    }
}

void solve(int i)
{
    if(i == 10)
    {
        bool canSolve = true;
        for(int x=0; x<10; x++)
            for(int y=0; y<10; y++)
                if(newboard[x][y]) canSolve = false;
        
        if(canSolve) ans = max(ans, cnt);
        return;
    }

    for(int j=0; j<10; j++)
        if(newboard[i-1][j]) bulb(i, j), cnt++;
    solve(i+1);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    for(int i=0; i<10; i++)
    {
        for(int j=0; j<10; j++)
        {
            char c; cin >> c;
            if(c == '#') board[i][j] = false;
            else board[i][j] = true;
        }
    }
    
    //맨 윗줄의 스위치를 모든 방법으로 누른다고 가정한다. 2^10-1번이 필요할 것이다.
    //n번째 줄의 전구 상태가 결정되면, n+1번째 줄에 누를 스위치는 자동으로 결정된다.
    //(i-1, j)의 전구가 켜져 있다면 반드시 (i, j)번째 스위치를 눌러야 하기 때문이다.
    //즉 2^10-1번의 반복으로도 문제를 해결할 수 있다.
    for(int i=0; i<(1<<10); i++)
    {
        for(int x=0; x<10; x++)
            for(int y=0; y<10; y++)
                newboard[x][y] = board[x][y];
        
        for(int j=0; j<10; j++)
            if(i & (1 << j)) bulb(0, j), cnt++;
        solve(1);
        cnt=0;
    }
    cout << ans;
}

 

20149번: 선분 교차 3 - 기하(CCW, 선분 교차)

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef tuple<int, int, int> tiii;
typedef complex<ld> coord;

#define X real()
#define Y imag()
coord p1, p2, p3, p4;

bool cmp(coord p1, coord p2) { return (p1.X < p2.X || p1.X == p2.X && p1.Y < p2.Y); }
coord p2v(coord p1, coord p2) { return {p2.X-p1.X, p2.Y-p1.Y}; }
ld CCW(coord v1, coord v2) { return (conj(v1)*v2).Y; }
void printCross()
{
    ld p = CCW((p3-p1), (p4-p3)) / CCW((p2-p1), (p4-p3));
    coord ans = p1 + p * (p2-p1);
    cout << fixed << setprecision(10) << ans.X << " " << ans.Y;
} //벡터의 직선의 방정식을 이용한 교차점 구하기

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    ld x1, y1, x2, y2, x3, y3, x4, y4;
    cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3 >> x4 >> y4;
    p1 = {x1, y1}, p2 = {x2, y2}, p3 = {x3, y3}, p4 = {x4, y4};
    if(cmp(p2, p1)) swap(p1, p2);
    if(cmp(p4, p3)) swap(p3, p4);
    
    coord v12 = p2v(p1, p2), v23 = p2v(p2, p3), v24 = p2v(p2, p4);
    coord v34 = p2v(p3, p4), v41 = p2v(p4, p1), v42 = p2v(p4, p2);
    ld ccw123 = CCW(v12, v23), ccw124 = CCW(v12, v24);
    ld ccw341 = CCW(v34, v41), ccw342 = CCW(v34, v42);
    ld ccw12 = ccw123 * ccw124;
    ld ccw34 = ccw341 * ccw342;
    
    if(ccw12 <= 0 && ccw34 <= 0)
    {
        if(ccw12 == 0 && ccw34 == 0)
        {
            if(cmp(p2, p3) || cmp(p4, p1)) cout << 0;
            else
            {
                cout << 1 << "\n";
                if(ccw123 == 0 && ccw124 == 0 && ccw341 == 0 && ccw342 == 0)
                {
                    if(p1 == p4) cout << p1.X << " " << p1.Y;
                    else if(p2 == p3) cout << p2.X << " " << p2.Y;
                } //네 점이 한 직선 위에 있을 경우, 한 선분의 큰 쪽이 다른 선분의 다른 쪽과 교차해야만 한다.
                else
                {
                    if(p1 == p3 || p1 == p4) cout << p1.X << " " << p1.Y;
                    else if(p2 == p3 || p2 == p4) cout << p2.X << " " << p2.Y;
                } //세 점이 한 직선 위에 있을 경우, 모든 끝점이 교차하는지 확인한다.
            }
        }
        else
        {
            cout << 1 << "\n";
            printCross();
        }
    }
    else cout << 0;
}
728x90
반응형

'알고리즘 > solved.ac - CLASS' 카테고리의 다른 글

CLASS 7 - P5  (0) 2024.08.10
CLASS 6 - P3  (1) 2024.06.16
CLASS 6 - P5  (1) 2024.06.02
CLASS 6 - G3~G1  (0) 2024.05.26
CLASS 5 - P5  (0) 2024.05.25

관련글 더보기

댓글 영역