week7 - 내장 정렬알고리즘, 도형 문제

하스코딩·2025년 5월 8일

문제1.

풀이

  • 이 문제는 c1,c2,c3 모든 조합에 대해 3중 for문으로 가능한 target이 있는지 확인할 수 있으나, 이렇게 하면 시간복잡도가 O(N^3)이 되므로 너무 크다.
  • 그래서 3중 for문을 돌되, 한 target t에 대해, c1, c2를 탐색하며 bianry_search로 가능한 c3가 cards 벡터에 존재하는지 찾아 O(N^2log2)로 시간복잡도를 낮췄다.
  • 만약 c3가 cards에 있다면 가장 바깥 for문의 target t는 가능한 t이므로 possible 플래그를 true로 설정하여 break로 c1,c2의 2중 for문을 탈출하도록 해 시간복잡도를 낮췄다.
  • 이때 binary_search는 algorithm 라이브러리의 binary_search메소드를 사용해 cards.begin(), cards.end(), c3를 전달해서 찾아주면 빠르게 bool 값을 얻을 수 있다.
  • 또한 가능한 당첨번호가 여러개라면 오름차순 정렬해 출력하라고 했으므로 algorithm 라이브러리의 sort()메소드에 result.begin(), result.end()를 전달해서 정렬해준다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> getPossibleTarget(vector<int>& cards, const vector<int>& targets) {

    vector<int> possibleTarget;//가능한 당첨번호 저장 벡터
    sort(cards.begin(), cards.end());//card 배열 시작위치,끝위치 인자 오름차순 정렬

    for (int i = 0; i < targets.size(); i++) {
        //1. 한 target t에 대해
        int t = targets[i];
        bool possible = false;

        //2. 정렬된 card 배열 탐색, c1와
        for (int j = 0; j < cards.size(); j++) {
            int c1 = cards[j];

            //3. c2에 대해
            for (int k = 0; k <= j; k++) {
                int c2 = cards[k];

                //t == (c1+c2) + c3 되는 c3를 구하고
                int c3 = t - (c1 + c2);
                //바이너리 서치로 c3를 cards에서 찾아 있으면 플래그 세우고, break
                if (binary_search(cards.begin(), cards.end(), c3) == true) {
                    possible = true;
                    break;
                }
            }
            //4. c1에 대한 c2 탐색 종료 후 있으면, 이번 target은 가능이므로 탈출
            if (possible) {
                break;
            }
        }
        //탈출해서 해당 target(t)를 가능 벡터에 저장
        if (possible) {
            possibleTarget.push_back(t);
        }
    }

    //최종 결과를 정렬해 반환
    sort(possibleTarget.begin(), possibleTarget.end());
    return possibleTarget;
}

int main() {

    //사용할 카드 수 n, 당첨 번호의 숫자 m 입력
    int n, m;
    cin >> n >> m;

    //n개의 카드에 적힌 수 입력
    vector<int> cards(n);
    for (int i = 0; i < n; i++) {
        cin >> cards[i];
    }

    //m개의 당첨 번호 입력
    vector<int> targets(m);
    for (int i = 0; i < m; i++) {
        cin >> targets[i];
    }

    //세카드 합으로 가능한 당첨번호 벡터 반환
    vector<int> result = getPossibleTarget(cards, targets);

    if (result.empty()) {//없으면 no
        cout << "NO" << endl;
    }
    else {//있으면 결과 출력
        for (int i = 0; i < result.size(); i++) {
            cout << result[i] << " ";
        }
    }

    return 0;
}

문제2. 직사각형

풀이

  • 이 문제는 직사각형의 대각선 좌표 두개를 사용해서 left, right, top, bottom 값을 구하면 쉽게 해결할 수 있다.
  • 직1의 l1,r1,t1,b1와 직2의 l2,r2,t2,b2 정보를 사용해서 교차된 직사각형의 넓이를 구하려면, 중앙으로 모여야 하므로 l은 오른쪽으로, r은 왼쪽으로, t는 아래쪽으로, b는 위쪽으로 좌표를 선정해야 한다.
  • 이렇게 선정한 l,r,t,b 정보가 l<=r && b<=t인 경우에는 넓이가 유효하므로 이를 계산해주면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int get_area(int l1, int r1, int t1, int b1, int l2, int r2, int t2, int b2) {
    
    //구할 직사각형 
    int l, r, t, b;

    l = max(l1, l2);
    r = min(r1, r2);
    t = min(t1, t2);
    b = max(b1, b2);
    
    //길이이므로 음수나오면 안되니까 조건 검사 후
    if (l <= r && b <= t) {
        return (r - l) * (t - b);//밑변*높이 리턴
    }   
}

void test_case() {
    //직사각형1 대각선 두 점 x,y좌표,
    int ax, ay, bx, by;
    //직사각형2 대각선 두 점 x,y좌표 입력
    int px, py, qx, qy;
    cin >> ax >> ay >> bx >> by >> px >> py >> qx >> qy;

    //직사각형1 계산
    int l1, r1, t1, b1;
    l1 = min(ax, bx);//왼쪽 x좌표
    r1 = max(ax, bx);//오른쪽 x좌표
    t1 = max(ay, by);//위 y좌표
    b1 = min(ay, by);//아래 y좌표

    //직사각형2 계산
    int l2, r2, t2, b2;
    l2 = min(px, qx);//왼쪽 x좌표
    r2 = max(px, qx);//오른쪽 x좌표
    t2 = max(py, qy);//위 y좌표
    b2 = min(py, qy);//아래 y좌표

    //넓이 반환
    int result = get_area(l1, r1, t1, b1, l2, r2, t2, b2);

    //넓이 출력
    cout << result << endl;
}

int main() {
    
    //테스트케이스 t 입력
    int t;
    cin >> t;
    
    //t개의 테스트 케이스에 4점x,y 좌표 총 8개 입력
    for (int i = 0; i < t; i++) {
        test_case();
    }
   
    return 0;
}

0개의 댓글