※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 7662번 문제인 이중 우선순위 큐이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/7662

 

7662번: 이중 우선순위 큐

입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 Q에 적

www.acmicpc.net

우선순위 큐(priority queue)는 자료의 추가가 수시로 이루어지는 경우, 우선순위가 가장 높은(또는 낮은) 자료를 항상 빠르게 꺼낼 수 있는 자료구조이다.

 

이 문제에서는 쿼리를 통해 자료를 빈번히 추가하고 우선순위가 가장 높은 자료 또는 가장 낮은 자료를 쿼리가 들어온 시점을 기준으로 제거한다.

이런 작업을 수행할 수 있는 우선순위 큐를 double-ended priority queue라고 한다.

 

double-ended priority queue를 구현하는 대표적인 방법 중 하나는 min-max heap을 이용하는 것이다.

그러나 이 문제는 자료구조를 처음서부터 코딩하라는 문제가 아니기에 글쓴이는 min-max heap을 직접 구현하지는 않았다.

min-max heap에 관심이 있다면 다음 위키백과 링크를 참고하자.

en.wikipedia.org/wiki/Min-max_heap

 

글쓴이는 stl에 들어있는 std::priority_queue를 활용하여 문제를 풀었다.

 

std::priority_queue는 max heap 자료구조인데, 정수 자료의 경우 자료를 넣을 때 -1을 곱해 넣고 꺼낼 때 다시 -1을 곱하는 방식으로 min heap으로도 사용할 수 있다.

(단, 일반적인(signed) int형의 경우 양수와 음수가 완전히 대응되지 않으므로 이에 주의한다.)

 

문제를 푼 방식은 단순하다.

 

1) 새로운 정수가 들어온다면 이 정수를 max heap과 min heap에 각각 넣는다.

 

2-1) 최댓값을 지우라는 명령이 들어오면 max heap에서 최댓값을 지우고, min heap에서 다음에 이 수가 나오면 지워야 한다고 기록해둔다. 이 수들은 min heap에서 숫자가 지워지는 순서대로 만나게 될 것이므로, 또 다른 min heap에 저장해두면 지워야 할 때 쉽게 확인하고 지울 수 있다.

 

2-2) 최솟값을 지우라는 명령이 들어오면 min heap서 최솟값을 지우고, max heap에서 다음에 이 수가 나오면 지워야 한다고 기록해둔다. 이 수들은 max heap에서 숫자가 지워지는 순서대로 만나게 될 것이므로, 또 다른 max heap에 저장해두면 지워야할 때 쉽게 확인하고 지울 수 있다.

 

3) max heap과 min heap에서 지워야 할 수를 모두 지운다.

 

4) 1~3을 반복한다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <queue>
using std::priority_queue;
using std::cin;
using std::cout;

void solve() {
    priority_queue<long long> mxpq;
    priority_queue<long long> mxpqchk;
    priority_queue<long long> mnpq;
    priority_queue<long long> mnpqchk;
    
    int k;
    cin >> k;
    
    char type;
    long long n;
    for (int i = 0;i < k;i++) {
        cin >> type >> n;
        if (type == 'I') {
            mxpq.push(n);
            mnpq.push(-1*n);
        }
        else {
            if (n == 1 and mxpq.size()!=0) {
                long long x = mxpq.top();
                mnpqchk.push(-1*x);
                mxpq.pop();
            }
            else if (n == -1 and mnpq.size()!=0) {
                long long x = -1*mnpq.top();
                mxpqchk.push(x);
                mnpq.pop();
            }
            int sz1 = mxpq.size();
            int sz2 = mxpqchk.size();
            while (sz1 != 0 and sz2 != 0) {
                if (mxpq.top() == mxpqchk.top()) {
                    mxpq.pop();
                    mxpqchk.pop();
                    sz1 = mxpq.size();
                    sz2 = mxpqchk.size();
                }
                else break;
            }
            sz1 = mnpq.size();
            sz2 = mnpqchk.size();
            while (sz1 != 0 and sz2 != 0) {
                if (mnpq.top() == mnpqchk.top()) {
                    mnpq.pop();
                    mnpqchk.pop();
                    sz1 = mnpq.size();
                    sz2 = mnpqchk.size();
                }
                else break;
            }
        }
    }
    if (mxpq.size()==0) cout << "EMPTY\n";
    else cout << mxpq.top() << ' ' << -1*mnpq.top() << "\n";
}

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

    int T;
    cin >> T;
    for (int i = 0;i < T;i++) {
        solve();
    }

    return 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 14686 // C++] Sum Game  (0) 2021.02.07
[BOJ 1107 // C++] 리모컨  (0) 2021.02.06
[BOJ 1780 // C++] 종이의 개수  (0) 2021.02.04
[BOJ 7569 // C++] 토마토  (0) 2021.02.03
[BOJ 16236 // C++] 아기 상어  (0) 2021.02.02

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 1780번 문제인 종이의 개수이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/1780

 

1780번: 종이의 개수

N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1의 세 값 중 하나가 저장되어 있다. 우리는 이 행렬을 적절한 크기로 자르려고 하는데, 이때 다음의 규칙에 따라 자르려고 한다.

www.acmicpc.net

이 문제는 분할정복(divide and conquer)으로 풀기 좋은 문제이다. 이 문제에서 다음과 같이 분할정복 알고리즘을 적용하자.

 

1) 만약 현재 조각이 한 값으로만 저장되어있다면 그 값의 종이가 하나 있는 것이다.

2) 그렇지 않다면, 종이를 가로 3등분, 세로 3등분 총 9조각 내어 각 조각에 대해 1부터 다시 진행한다.

 

아래는 제출한 소스코드이다.

#include <iostream>
using std::cin;
using std::cout;

int paper[2187][2187];
int m1 = 0, zero = 0, p1 = 0; // 각 종이의 개수를 세는 -1, 0, 1 변수

void solve(int N,int x, int y) {
    int num = paper[x][y];
    bool chk = true;
    for (int i = x;i < x + N;i++) { // 하나의 수로 이루어진 조각인지 확인
        for (int j = y;j < y + N;j++) {
            if (paper[i][j] != num) {
                chk = false;
            }
            if (!chk) break;
        }
        if (!chk) break;
    }
    if (chk) { // 하나의 수로 이루어진 조각이면 그 수에 대응되는 변수를 +1
        if (num == 1) p1++;
        else if (num == 0) zero++;
        else m1++;
    }
    else { // 아니라면 조각을 다시 9조각내어 이를 반복
        N /= 3;
        solve(N, x, y);
        solve(N, x + N, y);
        solve(N, x + 2 * N, y);
        solve(N, x, y + N);
        solve(N, x + N, y + N);
        solve(N, x + 2 * N, y + N);
        solve(N, x, y + 2 * N);
        solve(N, x + N, y + 2 * N);
        solve(N, x + 2 * N, y + 2 * N);
    }
}

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

    int N;
    cin >> N;
    for (int i = 0;i < N;i++) {
        for (int j = 0;j < N;j++) {
            int temp;
            cin >> temp;
            paper[i][j] = temp;
        }
    }

    solve(N, 0, 0);

    cout << m1 << '\n' << zero << '\n' << p1;

    return 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 1107 // C++] 리모컨  (0) 2021.02.06
[BOJ 7662 // C++] 이중 우선순위 큐  (0) 2021.02.05
[BOJ 7569 // C++] 토마토  (0) 2021.02.03
[BOJ 16236 // C++] 아기 상어  (0) 2021.02.02
[BOJ 15686 // C++] 치킨 배달  (0) 2021.02.01

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 7569번 문제인 토마토이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/7569

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,

www.acmicpc.net

2차원배열에서 주어진 점에서 가장 멀리 떨어진 점을 찾는 문제의 3차원 버전이라고 볼 수 있겠다.

성분을 하나 추가해서 확장하면 그대로 풀린다.

 

글쓴이는 tuple<int,int,int>를 담는 queue를 만들어 DFS로 풀어보았다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <queue>
#include <tuple>
using std::queue;
using std::cin;
using std::cout;
using std::tuple;
using std::make_tuple;

queue<tuple<int, int, int>> que;
using std::cin;
using std::cout;

int tomato[100][100][100];

int dx[6] = { 1,-1,0,0,0,0 };
int dy[6] = { 0, 0, 1,-1,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };

int main()
{ // 입력: 3차원 토마토 배열을 만들면서 토마토가 있는 위치를 queue에 넣는다
    int x, y, z;
    cin >> x >> y >> z;
    int temp;
    for (int k = 0;k < z;k++) {
        for (int j = 0;j < y;j++) {
            for (int i = 0;i < x;i++) {
                cin >> temp;
                tomato[i][j][k] = temp;
                if (temp == 1) {
                    que.push(make_tuple(i,j,k));
                }
            }
        }
    }
    int ans=1;
    while (!que.empty()) { // BFS
        tuple<int, int, int> current = que.front();
        que.pop();
        for (int i = 0;i < 6;i++) {
            int xx = std::get<0>(current) + dx[i];
            int yy = std::get<1>(current) + dy[i];
            int zz = std::get<2>(current) + dz[i];
            if (xx >= 0 and xx < x and yy >= 0 and yy < y and zz >= 0 and zz < z) {
                if (tomato[xx][yy][zz] == 0) {
                    tomato[xx][yy][zz] = tomato[std::get<0>(current)][std::get<1>(current)][std::get<2>(current)]+1;
                    que.push(make_tuple(xx, yy, zz));
                    if (tomato[xx][yy][zz] > ans) ans = tomato[xx][yy][zz];
                }
            }
        }
    }
    for (int k = 0;k < z;k++) { // 안 익은 토마토가 남아있는지 확인하기
        for (int j = 0;j < y;j++) {
            for (int i = 0;i < x;i++) {
                if (tomato[i][j][k] == 0) {
                    ans = 0;
                }
            }
        }
    }
    cout << ans-1;

    return 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 7662 // C++] 이중 우선순위 큐  (0) 2021.02.05
[BOJ 1780 // C++] 종이의 개수  (0) 2021.02.04
[BOJ 16236 // C++] 아기 상어  (0) 2021.02.02
[BOJ 15686 // C++] 치킨 배달  (0) 2021.02.01
[BOJ 14500 // C++] 테트로미노  (0) 2021.01.31

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 16236번 문제인 아기 상어이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

글쓴이는 이 문제를 아기상어가 먹을 수 없는 물고기를 벽으로 생각하고 BFS를 하여 "가장 거리가 가까운 먹을 수 있는  중 우선순위에 맞는 물고기"를 탐색해나가는 방식으로 풀었다.

이 문제를 풀면서, 코드를 깔끔히 사용하고, 반복되는 부분을 함수로 정의하거나 반복문을 활용하여 줄이는 연습을 더 해야겠다는 생각이 들었다.

 

글쓴이의 코드의 작동은 다음과 같이 이루어진다.

1) N by N 공간을 읽어온다.

1-1) 먹을 수 있는 물고기 벡터를 만든다.

1-2) 크기별 물고기 벡터를 만든다.

 

2) 아기 상어의 크기보다 큰 숫자가 적힌 칸을 벽의 조건으로 생각하고, bfs로 아기상어의 위치에서 가장 가까운 거리의 "먹을 수 있는 물고기"들을 찾는다:

2-1) bfs를 하면서 "지금까지 탐색하던 점보다 멀어진 거리의 점"을 밟았을 때, "먹을 수 있는 물고기" 벡터에 있는 물고기가 놓인 지점을 (문제 조건에 적힌 순서대로) 방문했는지 순서대로 확인해본다.

    2-1-1) 물고기를 발견한다면 출력할 답에 현재 물고기의 거리를 더한다. 물고기의 위치를 아기상어의 새로운 위치로 하고, 먹을 수 있는 물고기 벡터에서 해당 물고기를 지운다.

    2-1-2) 이 물고기를 먹어서 물고기가 커질 수 있는지 확인한다. 물고기가 커질 수 있다면 물고기의 크기를 키우고, 새로 먹을 수 있게 된 물고기들을 먹을 수 있는 물고기 벡터에 집어넣는다.

2-2) 먹을 수 있는 물고기가 아기 상어가 갈 수 있는 가장 먼 칸에만 존재할 수도 있다. 이 경우 2-1의 조건을 만족시키지 못해 빠져나가므로, 이 경우를 붙잡아 다시 위의 과정을 해준다.

2-3) 2-2를 했는데도 먹을 수 있는 물고기가 없었다면 더 이상 먹을 수 있는 물고기가 없는 것이다. 탐색을 종료한다.

 

아래는 제출한 소스코드이다. 매우 길어 접어둔다.

※ 많이 지저분하니 읽지 않는 것을 권장한다. ※

더보기
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using std::cin;
using std::cout;
using std::vector;
using std::pair;
using std::queue;

int N;
pair<int, int> babyshark;
int babysharksize = 2;
int babysharkexp = 0;
int ans = 0;
int graph[21][21];
int dist[21][21];

vector<pair<int, int>> delicious;
vector<pair<int, int>> size2;
vector<pair<int, int>> size3;
vector<pair<int, int>> size4;
vector<pair<int, int>> size5;
vector<pair<int, int>> size6;
vector<pair<int, int>>::iterator iter;
vector<pair<int, int>>::iterator sizereader;

int bfs() {
    queue<pair<int, int>> que;
    que.push(babyshark);
    bool notbreaked = true;
    for (int i = 0;i < 21;i++) {
        for (int j = 0;j < 21;j++) {
            dist[i][j] = 0;
        }
    }
    int currentdist = 0;
    bool ifcheck = false;
    while (!que.empty()) {
        pair<int, int> nextpoint;
        pair<int, int> current = que.front();
        que.pop();
        if (current.first != 0) {
            if (graph[current.first - 1][current.second] <= babysharksize and dist[current.first - 1][current.second] == 0) {
                nextpoint = { current.first - 1, current.second };
                que.push(nextpoint);
                dist[nextpoint.first][nextpoint.second] = dist[current.first][current.second] + 1;
            }
        }
        if (current.second != 0) {
            if (graph[current.first][current.second - 1] <= babysharksize and dist[current.first][current.second - 1] == 0) {
                nextpoint = { current.first, current.second - 1 };
                que.push(nextpoint);
                dist[nextpoint.first][nextpoint.second] = dist[current.first][current.second] + 1;
            }
        }
        if (current.first != N - 1) {
            if (graph[current.first + 1][current.second] <= babysharksize and dist[current.first + 1][current.second] == 0) {
                nextpoint = { current.first + 1, current.second };
                que.push(nextpoint);
                dist[nextpoint.first][nextpoint.second] = dist[current.first][current.second] + 1;
            }
        }
        if (current.second != N - 1) {
            if (graph[current.first][current.second + 1] <= babysharksize and dist[current.first][current.second + 1] == 0) {
                nextpoint = { current.first, current.second + 1 };
                que.push(nextpoint);
                dist[nextpoint.first][nextpoint.second] = dist[current.first][current.second] + 1;
            }
        }
        bool chk = false;
        if (dist[current.first][current.second] != currentdist) {
            currentdist++;
            for (iter = delicious.begin();iter != delicious.end();iter++) {
                pair<int, int> x = *iter;
                if (dist[x.first][x.second] != 0 and dist[x.first][x.second] < currentdist) {
                    ans += dist[x.first][x.second];
                    babyshark.first = x.first;
                    babyshark.second = x.second;
                    delicious.erase(iter);
                    babysharkexp++;
                    if (babysharkexp == babysharksize) {
                        babysharksize++;
                        babysharkexp = 0;
                        if (babysharksize == 3) {
                            for (sizereader = size2.begin();sizereader != size2.end();sizereader++) {
                                pair<int, int> y = *sizereader;
                                delicious.push_back(y);
                            }
                        }
                        if (babysharksize == 4) {
                            for (sizereader = size3.begin();sizereader != size3.end();sizereader++) {
                                pair<int, int> y = *sizereader;
                                delicious.push_back(y);
                            }
                        }
                        if (babysharksize == 5) {
                            for (sizereader = size4.begin();sizereader != size4.end();sizereader++) {
                                pair<int, int> y = *sizereader;
                                delicious.push_back(y);
                            }
                        }
                        if (babysharksize == 6) {
                            for (sizereader = size5.begin();sizereader != size5.end();sizereader++) {
                                pair<int, int> y = *sizereader;
                                delicious.push_back(y);
                            }
                        }
                        if (babysharksize == 7) {
                            for (sizereader = size6.begin();sizereader != size6.end();sizereader++) {
                                pair<int, int> y = *sizereader;
                                delicious.push_back(y);
                            }
                        }
                        sort(delicious.begin(), delicious.end());
                    }
                    chk = true;
                    ifcheck = true;
                    break;
                }
            }
        }
        if (chk) {
            notbreaked = false;
            break;
        }
        if (current == babyshark) {
            dist[current.first][current.second] = 1000000000;
        }
    }
    if (!ifcheck) {
        for (iter = delicious.begin();iter != delicious.end();iter++) {
            pair<int, int> x = *iter;
            if (dist[x.first][x.second] == currentdist and currentdist != 0) {
                ans += dist[x.first][x.second];
                babyshark.first = x.first;
                babyshark.second = x.second;
                delicious.erase(iter);
                babysharkexp++;
                if (babysharkexp == babysharksize) {
                    babysharksize++;
                    babysharkexp = 0;
                    if (babysharksize == 3) {
                        for (sizereader = size2.begin();sizereader != size2.end();sizereader++) {
                            pair<int, int> y = *sizereader;
                            delicious.push_back(y);
                        }
                    }
                    if (babysharksize == 4) {
                        for (sizereader = size3.begin();sizereader != size3.end();sizereader++) {
                            pair<int, int> y = *sizereader;
                            delicious.push_back(y);
                        }
                    }
                    if (babysharksize == 5) {
                        for (sizereader = size4.begin();sizereader != size4.end();sizereader++) {
                            pair<int, int> y = *sizereader;
                            delicious.push_back(y);
                        }
                    }
                    if (babysharksize == 6) {
                        for (sizereader = size5.begin();sizereader != size5.end();sizereader++) {
                            pair<int, int> y = *sizereader;
                            delicious.push_back(y);
                        }
                    }
                    if (babysharksize == 7) {
                        for (sizereader = size6.begin();sizereader != size6.end();sizereader++) {
                            pair<int, int> y = *sizereader;
                            delicious.push_back(y);
                        }
                    }
                    sort(delicious.begin(), delicious.end());
                }
                notbreaked = false;
                break;
            }
        }
    }

    if (notbreaked) return 0;
    else return 1;
}

int main()
{
    cin >> N;
    int x;
    for (int i = 0;i < N;i++) {
        for (int j = 0;j < N;j++) {
            cin >> x;
            if (x == 1) delicious.push_back({ i,j });
            if (x == 2) size2.push_back({ i,j });
            if (x == 3) size3.push_back({ i,j });
            if (x == 4) size4.push_back({ i,j });
            if (x == 5) size5.push_back({ i,j });
            if (x == 6) size6.push_back({ i,j });
            if (x == 9) {
                babyshark = { i,j };
                graph[i][j] = 0;
            }
            else graph[i][j] = x;
        }
    }
    for (int i = 0; i < N; i++) {
        graph[i][N] = 1000000000;
    }
    for (int j = 0; j < N; j++) {
        graph[N][j] = 1000000000;
    }

    bool chk = 1;
    while (chk) {
        chk = bfs();
    }

    cout << ans;

    return 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 1780 // C++] 종이의 개수  (0) 2021.02.04
[BOJ 7569 // C++] 토마토  (0) 2021.02.03
[BOJ 15686 // C++] 치킨 배달  (0) 2021.02.01
[BOJ 14500 // C++] 테트로미노  (0) 2021.01.31
[BOJ 11403 // C++] 경로 찾기  (0) 2021.01.30

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 15686번 문제인 치킨 배달이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/15686

 

15686번: 치킨 배달

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

www.acmicpc.net

이 문제는 숫자가 작아 나올 수 있는 경우의 수가 적으니 가능한 모든 경우를 탐색해서 풀었다.

 

1) 먼저 순열을 생성하는 recursion을 이용해 가능한 M개의 치킨집을 고르는 모든 경우의 수에 접근한다.

이 때, 각각의 치킨집을 pair의 형태로 좌표를 벡터에 저장해두면 순열을 생성하기 편해진다.

2) 각 집에서 현재 순열에 저장된 치킨집과의 거리중 최솟값들을 합한다. 이것이 현재 치킨집 순열에 대응되는 "도시의 치킨거리"이다.

3) 각 순열의 "도시의 치킨 거리" 중 최솟값을 구해 출력한다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
using std::vector;
using std::pair;
using std::cin;
using std::cout;

vector<pair<int, int>> chicken; // 모든 치킨집의 좌표를 저장한 벡터
vector<pair<int, int>> selectedchicken; // 치킨집의 순열을 저장할 벡터
vector<pair<int, int>> house; // 모든 집을 저장한 벡터

int min = 1000000000;

int dist(pair<int, int> pair1, pair<int, int> pair2) {
    return abs(pair1.first - pair2.first) + abs(pair1.second - pair2.second);
}

void func(int M, int cnt) { // recursion으로 치킨집의 순열의 경우의 수를 탐색
    vector<pair<int, int>>::iterator iterchicken;
    vector<pair<int, int>>::iterator iterhouse;
    if (selectedchicken.size() == M) { // 순열의 크기가 M이 되면
        int totaldist = 0; // totaldist: 도시의 치킨거리
        for (iterhouse = house.begin();iterhouse != house.end();iterhouse++) {
            int disttemp = 1000000000; // disttemp: 각 집의 치킨거리
            for (iterchicken = selectedchicken.begin();iterchicken != selectedchicken.end();iterchicken++) {
                int distance = dist(*iterhouse, *iterchicken);
                if (distance < disttemp) disttemp = distance;
            }
            totaldist += disttemp;
            if (min < totaldist) break; // 최적화: 다른 집들의 "치킨 거리"를 안 더해도 이미 답을 넘은 경우 탈출
        }
        if (min > totaldist) min = totaldist;
    }
    else { // 치킨집의 순열을 채우는 과정
        for (iterchicken = chicken.begin() + cnt; iterchicken != chicken.end();iterchicken++) {
            cnt++;
            selectedchicken.push_back(*iterchicken);
            func(M, cnt);
            selectedchicken.pop_back();
        }
    }
}


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

    int N, M;
    cin >> N >> M;
    int x;
    int k = 0;
    for (int i = 0;i < N;i++) {
        for (int j = 0;j < N;j++) {
            cin >> x;
            if (x == 1) house.push_back({ i,j });
            else if (x == 2) {
                chicken.push_back({ i,j });
                k++;
            }
        }
    }
    func(M, 0);

    cout << min;

    return 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 7569 // C++] 토마토  (0) 2021.02.03
[BOJ 16236 // C++] 아기 상어  (0) 2021.02.02
[BOJ 14500 // C++] 테트로미노  (0) 2021.01.31
[BOJ 11403 // C++] 경로 찾기  (0) 2021.01.30
[BOJ 1992 // C++] 쿼드트리  (0) 2021.01.29

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 14500번 문제인 테트로미노이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

이 문제는 보드판에 격자에 맞게끔 테트로미노를 하나 놓아 해당 칸에 적힌 숫자들의 총합이 최대가 되게끔 하는 문제이다.

 

모든 테트로미노의 모양을 빠짐없이 확인하는 것이 중요한 문제이다. 아래를 펼치면 가능한 모든 테트로미노의 모양을 1로 표현해두었다. 0은 빈 공간이다.

더보기

---

1111

 

111

100

 

111

010

 

111

001

 

110

011

 

011

110

 

100

111

 

010

111

 

001

111

 

11

11

 

11

10

10

 

10

11

10

 

10

10

11

 

10

11

01

 

01

11

10

 

11

01

01

 

01

11

01

 

01

01

11

 

1

1

1

1

---

아래는 제출한 소스코드이다.

#include <iostream>
using std::cin;
using std::cout;

int N, M;
int board[500][500];
int ans = 0;

void tetra(int i, int j) {
    int x;
    if (i + 3 < N) {
        x = board[i][j] + board[i + 1][j] + board[i + 2][j] + board[i + 3][j];
        if (ans < x) ans = x;
    }
    if (i + 2 < N and j + 1 < M) {
        x = board[i][j] + board[i + 1][j] + board[i + 2][j] + board[i][j + 1];
        if (ans < x) ans = x;
        x = board[i][j] + board[i + 1][j] + board[i + 2][j] + board[i + 1][j + 1];
        if (ans < x) ans = x;
        x = board[i][j] + board[i + 1][j] + board[i + 2][j] + board[i + 2][j + 1];
        if (ans < x) ans = x;
        x = board[i][j] + board[i + 1][j] + board[i + 1][j + 1] + board[i + 2][j + 1];
        if (ans < x) ans = x;
        x = board[i][j] + board[i][j + 1] + board[i + 1][j + 1] + board[i + 2][j + 1];
        if (ans < x) ans = x;
        x = board[i + 1][j] + board[i][j + 1] + board[i + 1][j + 1] + board[i + 2][j + 1];
        if (ans < x) ans = x;
        x = board[i + 2][j] + board[i][j + 1] + board[i + 1][j + 1] + board[i + 2][j + 1];
        if (ans < x) ans = x;
        x = board[i + 1][j] + board[i][j + 1] + board[i + 1][j + 1] + board[i + 2][j];
        if (ans < x) ans = x;
    }
    if (i + 1 < N and j + 1 < M){
        x = board[i][j] + board[i][j + 1] + board[i + 1][j] + board[i + 1][j + 1];
        if (ans < x) ans = x;
    }
    if (i + 1 < N and j + 2 < M) {
        x = board[i][j] + board[i][j + 1] + board[i][j + 2] + board[i + 1][j];
        if (ans < x) ans = x;
        x = board[i][j] + board[i][j + 1] + board[i][j + 2] + board[i + 1][j + 1];
        if (ans < x) ans = x;
        x = board[i][j] + board[i][j + 1] + board[i][j + 2] + board[i + 1][j + 2];
        if (ans < x) ans = x;
        x = board[i][j] + board[i][j + 1] + board[i + 1][j + 1] + board[i + 1][j + 2];
        if (ans < x) ans = x;
        x = board[i][j] + board[i + 1][j] + board[i + 1][j + 1] + board[i + 1][j + 2];
        if (ans < x) ans = x;
        x = board[i][j + 1] + board[i + 1][j] + board[i + 1][j + 1] + board[i + 1][j + 2];
        if (ans < x) ans = x;
        x = board[i][j + 2] + board[i + 1][j] + board[i + 1][j + 1] + board[i + 1][j + 2];
        if (ans < x) ans = x;
        x = board[i][j + 1] + board[i + 1][j] + board[i + 1][j + 1] + board[i][j + 2];
        if (ans < x) ans = x;
    }
    if (j + 3 < M) {
        x = board[i][j] + board[i][j + 1] + board[i][j + 2] + board[i][j + 3];
        if (ans < x) ans = x;
    }
}

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

    cin >> N >> M;
    int x;
    for (int i = 0;i < N;i++) {
        for (int j = 0;j < M;j++) {
            cin >> x;
            board[i][j] = x;
        }
    }
    for (int i = 0;i < N;i++) {
        for (int j = 0;j < M;j++) {
            tetra(i, j);
        }
    }

    cout << ans;

    return 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 16236 // C++] 아기 상어  (0) 2021.02.02
[BOJ 15686 // C++] 치킨 배달  (0) 2021.02.01
[BOJ 11403 // C++] 경로 찾기  (0) 2021.01.30
[BOJ 1992 // C++] 쿼드트리  (0) 2021.01.29
[BOJ 1963 // C++] 소수 경로  (0) 2021.01.28

+ Recent posts