출처 : https://www.acmicpc.net/problem/21608
풀이 방법
호흡이 길 뿐 어려운 문제는 아니다 순서대로 하나씩 배열한 후 점수를 구하면 된다.
다음 좌석을 구하기 위해 선호하는 학생 수 , 빈자리 수, y가 작은, x가 작은으로 정렬을 하기 위해 모든 자리를 돌며 우선순위 큐를 사용해서 다음 자리를 선택했다.
주의 점
- 기본적인 우선순위 큐는 MAX Heap이다
- bool operator < (const Seat& a) const {
- 위 함수는 작은 경우 true를 리턴해야 하므로 주의해야 한다.
- 일반적인 sort에서 사용하려는 사용자 정의 cmp은 다름
- 점수 계산시 모든 좌석을 배정 다 한 후 해야 한다.
전체 코드
#include <iostream>
#include <vector>
#include <queue>
#include <memory.h>
using namespace std;
int N, student_num, ans;
vector<vector<int > > likes;
vector<int> order;
int school[21][21];
int point[21][21];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
struct Seat {
int y;
int x;
int like_cnt;
int empty_cnt;
Seat(int y, int x, int like_cnt, int empty_cnt) : x(x), y(y), like_cnt(like_cnt), empty_cnt(empty_cnt) {
}
bool operator < (const Seat& a) const {
if (like_cnt < a.like_cnt) return true; // like_cnt가 클수록 우선
else if (like_cnt == a.like_cnt) {
if (empty_cnt < a.empty_cnt) {
return true; // empty_cnt가 클수록 우선
}
else if (empty_cnt == a.empty_cnt) {
if (y > a.y) {
return true; // y가 작을수록 우선
}
else if (y == a.y) {
if (x > a.x) {
return true; // x가 작을수록 우선
}
else return false;
}
}
else return false;
}
else return false;
}
};
pair<int, int> count_like(int idx, int y, int x) { // 호감도 수, 빈 공간 수 계산
int like_cnt = 0, empty_cnt = 0;
for (int i =0;i < 4;i++) {
int ny = y + dy[i];
int nx = x + dx[i];
if( ny < 1 || ny >= N+1 || nx < 1 || nx >= N+1) continue;
int people = school[ny][nx];
if (people == 0) empty_cnt++;
for (int k = 0;k < 4;k++) { // 선호하는 사람인지 체크하는 함수
if (people == likes[idx][k]) {
like_cnt++;
continue;
}
}
}
return make_pair(like_cnt, empty_cnt);
}
Seat find_seat(int idx) { // 다음 좌석
priority_queue<Seat> s;
for (int i = 1;i <= N;i++) {
for (int j = 1;j <= N;j++) {
if (school[i][j] == 0) { //빈 자리이면 후보에 추가
pair<int, int> p = count_like(idx, i, j);
s.push(Seat(i, j, p.first, p.second));
}
}
}
return s.top(); // 우선순위 큐를 사용해 정렬
}
void cal_point() {
for (int i = 1;i < N+1;i++) {
for (int j = 1;j < N+1;j++) {
int idx = school[i][j];
for(int k = 0;k < 4;k++) {
int ny = i + dy[k];
int nx = j + dx[k];
if (ny < 1 || ny > N || nx < 1 || nx > N) continue;
int people = school[ny][nx], cnt = 0;
for (int z = 0; z < 4; z++) {
if (people == likes[idx][z]) {
cnt++;
continue;
}
}
point[i][j] += cnt;
}
}
}
int total_point = 0;
for (int i = 1;i < N+1;i++) {
for (int j = 1;j < N+1;j++) {
if (point[i][j] == 1) total_point += 1;
else if (point[i][j] == 2) total_point += 10;
else if (point[i][j] == 3) total_point += 100;
else if (point[i][j] == 4)total_point += 1000;
}
}
ans = total_point;
}
void sol() {
for (int i = 0;i < student_num;i++) {
Seat s = find_seat(order[i]);
school[s.y][s.x] = order[i];
}
}
int main() {
cin >> N;
student_num = N*N;
memset(school, 0, sizeof(school));
memset(point, 0, sizeof(point));
likes.resize(student_num+1);
for (int i = 0;i < student_num;i++) {
int a, b, c, d, e;
cin >> a >> b >> c >> d >> e;
order.push_back(a);
likes[a].push_back(b);
likes[a].push_back(c);
likes[a].push_back(d);
likes[a].push_back(e);
}
sol();
cal_point();
cout << ans << endl;
return 0;
}
'Algorithm' 카테고리의 다른 글
[백준] 집합 11723번 (c++) 비트마스킹 (0) | 2024.10.26 |
---|---|
[코드트리] 고대 문명 유적 탐사 (c++) 구현 (0) | 2024.10.26 |
[백준] 선 긋기 2170번 (C++) 라인스와핑 (1) | 2024.10.10 |
[백준] 미세먼지 안녕! 17144번 (c++) 구현, 로컬 배열 선언의 중요, 탐색 순서의 중요 (1) | 2024.10.03 |
[백준] 수 묶기 1744번 (c++) 그리디, 수를 잘 나누기 (0) | 2024.10.02 |