danbibibi
article thumbnail

1. 문제

문제 바로가기> BOJ 21608번: 상어 초등학교

 

21608번: 상어 초등학교

상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N2명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N2번까지 번호

www.acmicpc.net

 

2. 풀이

문제를 풀 때 중요하다고 느낀 점을 몇가지 적어보겠다.

 

1. 자리를 정할 때 우선순위 별로 정렬하기 위해 priority_queue를 이용

   * 이때, 구조체 내 연산자 재정의 방법을 알고 있어야 한다.

      (좋아하는 학생 수 > 빈칸 > 작은 행 번호 > 작은 열 번호) 우선으로 연산자 재정의를 해주어야 하기 때문!

 

2. 이미 자리가 정해진 경우 continue 해주기

    이미 자리가 정해졌는데, 그 자리를, pq 에 넣을 필요가 없다. 오히려 덮어씌워질 우려가,,

 

3. order_to_num 배열을 이용해 학생의 순서와 번호를 매핑 시켜주기!

    주어진 순서(!=번호)대로 자리를 배정하고, 

    나중에 만족도를 구할 때, 어느 학생(학생 번호)이 어디 앉았는지 알고 있어야 하기 때문!

 

<cpp />
#include<iostream> #include<vector> #include<queue> #define MAX 21 #define MAX2 450 #define EMPTY 0 using namespace std; struct DATA { int like, empty, row, col; bool operator < (const DATA &d) const { if (like == d.like) { if (empty == d.empty) { if (row == d.row) return col > d.col; // 열의 번호가 가장 작은 칸 return row > d.row; // 행의 번호가 가장 작은 칸 } return empty < d.empty; // 인접한 칸 중에서 비어있는 칸이 가장 많은 칸 } return like < d.like; // 좋아하는 학생이 인접한 칸에 가장 많은 칸 } }; int N; int seat[MAX][MAX]; int order_to_num[MAX2]; vector<int> student[MAX2]; int dy[] = { -1, 1, 0, 0 }; int dx[] = { 0, 0, -1, 1 }; int satisfy[] = { 0, 1, 10, 100, 1000 }; void input() { cin >> N; int n, s; for (int i = 0; i < N*N; i++) { cin >> n; // 학생의 번호 order_to_num[i] = n; for (int j = 0; j < 4; j++) { // 그 학생이 좋아하는 학생 4명의 번호 cin >> s; student[n].push_back(s); } } } void set_seat(int num) { priority_queue<DATA> pq; for (int y = 0; y < N; y++) { for (int x = 0; x < N; x++) { if (seat[y][x]) continue; // 이미 주인이 있는 자리 int like = 0, empty = 0; for (int d = 0; d < 4; d++) { int ny = y + dy[d]; int nx = x + dx[d]; if (ny < 0 || ny >= N || nx < 0 || nx >= N) continue; // 범위를 벗어나는 경우 for (int l = 0; l < 4; l++) { // 좋아하는 학생 if (seat[ny][nx] == student[num][l]) like++; } if (seat[ny][nx] == EMPTY) empty++; // 빈자리 } pq.push({ like, empty, y, x }); } } seat[pq.top().row][pq.top().col] = num; } void get_satisfy() { int ans = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { int like = 0; int num = seat[i][j]; for (int d = 0; d < 4; d++) { int ny = i + dy[d]; int nx = j + dx[d]; if (ny < 0 || ny >= N || nx < 0 || nx >= N) continue; for (int l = 0; l < 4; l++) { if (seat[ny][nx] == student[num][l]) like++; } } ans += satisfy[like]; } } cout << ans; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); input(); for (int i = 0; i < N * N; i++) set_seat(order_to_num[i]); get_satisfy(); }

'문제 풀이 > SW 역량 테스트' 카테고리의 다른 글

BOJ 14891번: 톱니바퀴  (0) 2023.01.23
BOJ 14890번: 경사로  (0) 2023.01.22
BOJ 23290번: 마법사 상어와 복제  (0) 2023.01.16
BOJ 17143번: 낚시왕  (0) 2023.01.15
BOJ 17144번: 미세먼지 안녕!  (0) 2023.01.12
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로