λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
λ°±μ€€/Gold

[BOJ] 21608 : 상어 μ΄ˆλ“±ν•™κ΅

by Jaeguk 2022. 5. 31.
문제 링크

21608번: 상어 μ΄ˆλ“±ν•™κ΅ (acmicpc.net)

 

21608번: 상어 μ΄ˆλ“±ν•™κ΅

상어 μ΄ˆλ“±ν•™κ΅μ—λŠ” ꡐ싀이 ν•˜λ‚˜ 있고, ꡐ싀은 N×N 크기의 격자둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. 학ꡐ에 λ‹€λ‹ˆλŠ” ν•™μƒμ˜ μˆ˜λŠ” N2λͺ…이닀. μ˜€λŠ˜μ€ λͺ¨λ“  ν•™μƒμ˜ 자리λ₯Ό μ •ν•˜λŠ” 날이닀. 학생은 1λ²ˆλΆ€ν„° N2λ²ˆκΉŒμ§€ 번호

www.acmicpc.net

쑰건에 맞게 학생듀을 μžλ¦¬μ— λ°°μΉ˜ν•˜λŠ” λ‹¨μˆœ κ΅¬ν˜„ 문제.

풀이

μžλ¦¬μ— λ°°μΉ˜ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ 정보

1. 각 학생듀이 μ’‹μ•„ν•˜λŠ” ν•™μƒμ˜ 번호

2. 학생듀을 배치 ν•  μˆœμ„œ

1λ²ˆμ€ LikeλΌλŠ” intν˜• 벑터λ₯Ό λ°°μ—΄λ‘œ μ„ μ–Έν•΄μ„œ 정보λ₯Ό μ €μž₯ν–ˆλ‹€. Like[ i ]μ—λŠ” i학생이 μ’‹μ•„ν•˜λŠ” ν•™μƒλ“€μ˜ λ²ˆν˜Έκ°€ λ“€μ–΄κ°€μžˆλ‹€.

2번 학생듀을 배치 ν•  μˆœμ„œ λŠ” StudentλΌλŠ” intν˜• 벑터λ₯Ό λ§Œλ“€μ–΄μ„œ μž…λ ₯λ˜λŠ” μˆœμ„œλŒ€λ‘œ ν•™μƒλ“€μ˜ 번호λ₯Ό μ €μž₯ν–ˆλ‹€.

1. λΉ„μ–΄μžˆλŠ” μΉΈ μ€‘μ—μ„œ μ’‹μ•„ν•˜λŠ” 학생이 μΈμ ‘ν•œ 칸에 κ°€μž₯ λ§Žμ€ 칸으둜 자리λ₯Ό μ •ν•œλ‹€.
2. 1을 λ§Œμ‘±ν•˜λŠ” 칸이 μ—¬λŸ¬ 개이면, μΈμ ‘ν•œ μΉΈ μ€‘μ—μ„œ λΉ„μ–΄μžˆλŠ” 칸이 κ°€μž₯ λ§Žμ€ 칸으둜 자리λ₯Ό μ •ν•œλ‹€.
3. 2λ₯Ό λ§Œμ‘±ν•˜λŠ” 칸도 μ—¬λŸ¬ 개인 κ²½μš°μ—λŠ” ν–‰μ˜ λ²ˆν˜Έκ°€ κ°€μž₯ μž‘μ€ 칸으둜, κ·ΈλŸ¬ν•œ 칸도 μ—¬λŸ¬ 개이면 μ—΄μ˜ λ²ˆν˜Έκ°€ κ°€μž₯ μž‘μ€ 칸으둜 자리λ₯Ό μ •ν•œλ‹€.​

μœ„μ˜ 쑰건을 μˆœμ„œλŒ€λ‘œ μ μš©μ‹œν‚€λ©΄ λœλ‹€.

1번 쑰건에 따라 λ¨Όμ € λͺ¨λ“  칸을 λŒλ©΄μ„œ ν•΄λ‹Ή 칸이 빈칸이면, 해당칸에 λŒ€ν•΄μ„œ μΈμ ‘ν•œ μΉΈ(4μΉΈ) 쀑 ν˜„μž¬ μžλ¦¬μ— 앉을 학생( i 학생)이 μ’‹μ•„ν•˜λŠ” 학생이 κ°€μž₯ λ§Žμ€ μΉΈλ“€μ˜ 인덱슀λ₯Ό Whereμ΄λΌλŠ” 벑터에 μ €μž₯ν•΄λ‘”λ‹€.

μ΄λ•Œ, λ§Œμ•½ Where λ²‘ν„°μ˜ 크기가 1이면 λ“€μ–΄κ°ˆ μžλ¦¬κ°€ ν•˜λ‚˜λΏμ΄λΌλŠ” λœ»μ΄λ―€λ‘œ ν•΄λ‹Ή μΈλ±μŠ€μ— i 학생을 μ•‰νžŒλ‹€.

Where λ²‘ν„°μ˜ 크기가 2이상이라면 2번 쑰건을 μ μš©μ‹œμΌœμ•Όν•œλ‹€.

2번 쑰건에 따라 Where에 λ“€μ–΄μžˆλŠ” 인덱슀λ₯Ό λŒλ©΄μ„œ μΈμ ‘ν•œ μΉΈ 쀑 빈칸이 κ°€μž₯ λ§Žμ€ 자리의 인덱슀λ₯Ό λ‹€μ‹œ ν•œ 번 Where 벑터에 λ„£λŠ”λ‹€.

λ¬Όλ‘  μ΄λ•Œ 기쑴에 Where에 λ“€μ–΄μžˆλ˜ 값은 λΉΌμ£Όκ³  μƒˆλ‘œμš΄ κ°’λ§Œ λ„£μ–΄μ£Όμ–΄μ•Όν•œλ‹€. κ·Έλž˜μ„œ λ‚˜λŠ” TempλΌλŠ” 벑터에 인접 μΉΈ 쀑 빈칸이 κ°€μž₯ λ§Žμ€ 인덱슀λ₯Ό 넣어두고 λ§ˆμ§€λ§‰μ— Where = Temp 라고 해쀬닀.

2번 쑰건을 μ μš©μ‹œν‚¨ ν›„ Where λ²‘ν„°μ˜ 크기가 1이면 ν•΄λ‹Ή μžλ¦¬μ— i 학생을 μ•‰νžŒλ‹€.

Where λ²‘ν„°μ˜ 크기가 2이상이라면 3번 쑰건에 따라 Where 벑터λ₯Ό μ •λ ¬ν•΄μ€€ ν›„ κ°€μž₯ μ•žμ—μžˆλŠ” μΈλ±μŠ€μ— i 학생을 μ•‰νžˆλ©΄ 끝.

μ΄λ ‡κ²Œ λͺ¨λ“  학생듀을 μ•‰κ²Œν•˜κ³  λ‚˜μ„œ λͺ¨λ“  칸을 λŒλ©΄μ„œ ν•΄λ‹Ή ν•™μƒλ“€μ˜ λ§Œμ‘±λ„λ₯Ό ansλΌλŠ” λ³€μˆ˜μ— 더해쀬닀.

λ§ˆμ§€λ§‰μ— ansλ₯Ό 좜λ ₯ν•΄μ£Όλ©΄ 끝이닀.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <stack>
#include <vector>
#include <math.h>
#include <queue>
#include <climits>
#include <deque>
#include <algorithm>
#include <iomanip>
#include <map>
#define mod 998244353
using namespace std;
typedef long long ll;
typedef priority_queue<pair<intint>vector<pair<intint>>, greater<pair<intint>>> Priority_queue;
const int INF = INT_MAX;
const int MAX_N = 400 + 5;
int N, Q;
int dx[] = {-1,0,1,0};
int dy[] = {0,1,0,-1};
vector<int> Like[MAX_N];
vector<int> Student;
int A[MAX_N][MAX_N];
vector<pair<intint>> Where;
 
bool is_ok(pair<intint>);
void num_one(int std);
void num_two();
bool is_like(int stdint like);
 
int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> N;
    for (int i = 1; i <= N * N; i++) {
        int Std;
        cin >> Std;
        Student.push_back(Std);
        for (int j = 0; j < 4; j++) {
            int like; cin >> like;
            Like[Std].push_back(like);
        }
    }
    for (int i = 0; i < Student.size(); i++) {
        Where.clear();
        int now = Student[i];
        num_one(now);
        if (Where.size() == 1) {
            A[Where[0].first][Where[0].second] = now;
            continue;
        }
        num_two();
        if (Where.size() == 1) {
            A[Where[0].first][Where[0].second] = now;
            continue;
        }
            sort(Where.begin(), Where.end());
            A[Where[0].first][Where[0].second] = now;
    }
    int ans = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            int now = A[i][j];
            int cnt = 0;
            for (int k = 0; k < 4; k++) {
                pair<intint> next = { i + dy[k], j + dx[k] };
                if (is_ok(next) && is_like(now, A[next.first][next.second]))
                    cnt++;
            }
            if (cnt == 0)
                continue;
            ans += (int)pow(10, cnt - 1);
        }
    }
    cout << ans << "\n";
    return 0;
}
 
void num_one(int std) {
    int Max = -1;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            if (A[i][j])
                continue;
            int cnt = 0;
            for (int k = 0; k < 4; k++) {
                pair<intint> next = { i + dy[k], j + dx[k] };
                if (is_ok(next) && is_like(std, A[next.first][next.second]))
                    cnt++;
            }
            if (cnt > Max) {
                Max = cnt;
                Where.clear();
                Where.push_back({ i,j });
            }
            else if (cnt == Max)
                Where.push_back({ i,j });
        }
    }
}
 
void num_two() {
    int Max = -1;
    vector<pair<int,int>> temp;
    for (int i = 0; i < Where.size(); i++) {
        pair<intint> now = Where[i];
        int cnt = 0;
        for (int j = 0; j < 4; j++) {
            pair<intint> next = { now.first + dy[j], now.second + dx[j] };
            if (is_ok(next) && !A[next.first][next.second])
                cnt++;
        }
        if (cnt > Max) {
            Max = cnt;
            temp.clear();
            temp.push_back(now);
        }
        else if (cnt == Max)
            temp.push_back(now);
    }
    Where = temp;
}
 
bool is_like(int stdint like) {
    for (int i = 0; i < Like[std].size(); i++) {
        if (Like[std][i] == like)
            return true;
    }
    return false;
}
 
bool is_ok(pair<intint> now) {
    if (now.first < 1 || now.first > N || now.second < 1 || now.second > N)
        return false;
    return true;
}
cs

 μ—¬κΈ°μ„œ μ’‹μ•„ν•˜λŠ” 학생인지 μ•„λ‹Œμ§€λ₯Ό 이차원 bool 배열을 μ΄μš©ν•΄μ„œ ν‘œν˜„ν•œλ‹€λ©΄, 

예λ₯Όλ“€μ–΄ bool is_like[ i ][ j ] κ°€ trueλ©΄ iκ°€ jλ₯Ό μ’‹μ•„ν•˜λŠ”λ‹€λŠ” λœ»μ΄λ‹€.

μ΄λ ‡κ²Œ ν•˜λ©΄ 학생 iκ°€ 학생 jλ₯Ό μ’‹μ•„ν•˜λŠ”μ§€λ₯Ό O(1)λ§Œμ— νŒλ³„ν•  수 μžˆλ‹€.

기쑴의 λ‚΄ μ½”λ“œλŠ” iκ°€ μ’‹μ•„ν•˜λŠ” ν•™μƒλ“€μ˜ λͺ©λ‘μ— jκ°€ λ“€μ–΄μžˆλŠ”μ§€ νŒλ‹¨ν•˜λ―€λ‘œ μ΅œλŒ€ O(4) 만큼의 μ‹œκ°„μ΄ κ±Έλ¦°λ‹€.

λŒ€μ‹  bool 이차원 배열을 μ„ μ–Έν•΄μ•Όν•˜λ―€λ‘œ λ©”λͺ¨λ¦¬κ°€ 쑰금 더 쓰일 것같닀.

728x90