문제 링크입니다: www.acmicpc.net/problem/21608
21608번: 상어 초등학교
상어 초등학교에는 교실이 하나 있고, 교실은 N×N 크기의 격자로 나타낼 수 있다. 학교에 다니는 학생의 수는 N2명이다. 오늘은 모든 학생의 자리를 정하는 날이다. 학생은 1번부터 N2번까지 번호
www.acmicpc.net
단순 구현 문제였습니다.
알고리즘은 아래와 같습니다.
1. 각 학생마다 좋아하는 학생들이 4명이 있으므로 해당 정보를 map 자료구조로 저장합니다. (likeFriends)
2. 입력받은 학생 순서로 자리를 배치하는데 문제에서 주어진 규칙대로 배치를 진행하면 됩니다.
- 비어있는 칸 중에서 좋아하는 학생이 인접한 칸에 가장 많은 칸으로 자리를 정한다.
- 1을 만족하는 칸이 여러 개이면, 인접한 칸 중에서 비어있는 칸이 가장 많은 칸으로 자리를 정한다.
- 2를 만족하는 칸도 여러 개인 경우에는 행의 번호가 가장 작은 칸으로, 그러한 칸도 여러 개이면 열의 번호가 가장 작은 칸으로 자리를 정한다.
3. 만족도를 구해줍니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <algorithm> | |
#include <map> | |
using namespace std; | |
const int MAX = 20; | |
const int FRIENDS_MAX = 4; | |
const int INF = 400 + 40; | |
typedef struct | |
{ | |
int y, x; | |
} Coord; | |
typedef struct | |
{ | |
int y, x; | |
} Dir; | |
Dir moveDir[MAX] = { {-1, 0}, {0, -1}, {0, 1}, {1, 0} }; | |
int N; | |
int classRoom[MAX][MAX]; | |
map<int, vector<int>> likeFriends; | |
bool doesContainLikeFriend(vector<int> friendList, int adjacentStudent) | |
{ | |
for (int i = 0; i < FRIENDS_MAX; i++) | |
{ | |
if (friendList[i] == adjacentStudent) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
void placeStudent(int student) | |
{ | |
int likeFriendCnt = 0; | |
int adjacentEmptySeatCnt = 0; | |
Coord coord = { INF, INF }; | |
for (int y = 0; y < N; y++) | |
{ | |
for (int x = 0; x < N; x++) | |
{ | |
if (classRoom[y][x]) | |
{ | |
continue; | |
} | |
int tempLikeFriendCnt = 0; | |
int tempAdjacentEmptySeatCnt = 0; | |
for (int k = 0; k < 4; k++) | |
{ | |
int nextY = y + moveDir[k].y; | |
int nextX = x + moveDir[k].x; | |
if (nextY < 0 || nextY >= N || nextX < 0 || nextX >= N) | |
{ | |
continue; | |
} | |
int adjacentStudent = classRoom[nextY][nextX]; | |
// 옆자리가 빈자리 | |
if (adjacentStudent == 0) | |
{ | |
tempAdjacentEmptySeatCnt++; | |
continue; | |
} | |
// 옆자리가 좋아하는 친구 | |
if (doesContainLikeFriend(likeFriends[student], adjacentStudent)) | |
{ | |
tempLikeFriendCnt++; | |
} | |
} | |
// 첫 번째 조건: 좋아하는 학생이 인접한 칸에 가장 많은 칸 | |
if (tempLikeFriendCnt > likeFriendCnt) | |
{ | |
likeFriendCnt = tempLikeFriendCnt; | |
adjacentEmptySeatCnt = tempAdjacentEmptySeatCnt; | |
coord = { y, x }; | |
continue; | |
} | |
// 두 번째 조건: 인접한 칸 중에서 비어있는 칸이 가장 많은 칸 | |
if (likeFriendCnt == tempLikeFriendCnt) | |
{ | |
if (tempAdjacentEmptySeatCnt > adjacentEmptySeatCnt) | |
{ | |
adjacentEmptySeatCnt = tempAdjacentEmptySeatCnt; | |
coord = { y, x }; | |
continue; | |
} | |
// 세 번째 조건: 행의 번호가 가장 작은 칸, 행이 동일할 경우 열의 번호가 가장 작은 칸 | |
if (adjacentEmptySeatCnt == tempAdjacentEmptySeatCnt) | |
{ | |
if (coord.y > y || (coord.y == y && coord.x > x)) | |
{ | |
coord = { y, x }; | |
} | |
} | |
} | |
} | |
} | |
classRoom[coord.y][coord.x] = student; | |
} | |
int calculateSatisfaction(void) | |
{ | |
int satisfaction = 0; | |
for (int y = 0; y < N; y++) | |
{ | |
for (int x = 0; x < N; x++) | |
{ | |
int student = classRoom[y][x]; | |
vector<int> friends = likeFriends[student]; | |
int likeFriendCnt = 0; | |
for (int k = 0; k < 4; k++) | |
{ | |
int nextY = y + moveDir[k].y; | |
int nextX = x + moveDir[k].x; | |
if (nextY < 0 || nextY >= N || nextX < 0 || nextX >= N) | |
{ | |
continue; | |
} | |
int adjacentStudent = classRoom[nextY][nextX]; | |
for (int likeFriend : friends) | |
{ | |
if (likeFriend == adjacentStudent) | |
{ | |
likeFriendCnt++; | |
break; | |
} | |
} | |
} | |
switch (likeFriendCnt) | |
{ | |
case 0: | |
break; | |
case 1: | |
satisfaction += 1; | |
break; | |
case 2: | |
satisfaction += 10; | |
break; | |
case 3: | |
satisfaction += 100; | |
break; | |
case 4: | |
satisfaction += 1000; | |
break; | |
} | |
} | |
} | |
return satisfaction; | |
} | |
int main(void) | |
{ | |
ios_base::sync_with_stdio(0); | |
cin.tie(0); | |
cin >> N; | |
vector<int> students(N*N); | |
for (int i = 0; i < N*N; i++) | |
{ | |
cin >> students[i]; | |
vector<int> friends(FRIENDS_MAX); | |
for (int j = 0; j < FRIENDS_MAX; j++) | |
{ | |
cin >> friends[j]; | |
} | |
likeFriends[students[i]] = friends; | |
} | |
for (int i = 0; i < N*N; i++) | |
{ | |
placeStudent(students[i]); | |
} | |
int result = calculateSatisfaction(); | |
cout << result << "\n"; | |
return 0; | |
} |


개발환경:Visual Studio 2017
지적, 조언, 질문 환영입니다! 댓글 남겨주세요~
반응형
'알고리즘 > BOJ' 카테고리의 다른 글
백준 21610번 마법사 상어와 비바라기 (1) | 2021.04.29 |
---|---|
백준 21609번 상어 중학교 (1) | 2021.04.28 |
백준 19771번 Сапсан (0) | 2021.04.27 |
C++ 백준 2935번 소음 (0) | 2021.04.26 |
백준 2921번 도미노 (0) | 2021.04.25 |