-
백준 15898번 피아의 아틀리에 ~신비한 대회의 연금술사~PS 2020. 1. 28. 16:48
https://www.acmicpc.net/problem/15898
15898번: 피아의 아틀리에 ~신비한 대회의 연금술사~
"피아의 아틀리에 ~신비한 대회의 연금술사~"는 가난한 연금술사 피아의 성장스토리를 담은 게임이다. 이 게임의 가장 중요한 부분은 "대회"인데, 연금술로 높은 품질의 물건을 만들어 상금을 타야만 피아가 먹고 살 수 있기 때문이다. 스토리는 매우 길지만 여백이 없어 생략하기로 하고, 여러분은 이 게임의 대회 기능을 확인해달라는 요청을 받았다. 여러분이 확인해야 하는 대회는 다음과 같다. 여러분은 5×5 격자 모양 가마에 서로 다른 재료 3개를 순서대로 넣어
www.acmicpc.net
<접근방법>
처음에는 dfs0 기저에서 dfs1 호출, dfs1 기저에서 dfs2 호출, dfs2 기저에서 계산...
이렇게 하려고 했습니다.
그런데 가마상태 관리를 어떻게 해야할지 도저히 모르겠어서 다른 분의 코드를 참고하였습니다.
하나의 dfs로 3개의 다른 상태에 대한 완전탐색을 합니다.
이때 가마의 현재 상태를 매개변수로 넘기면서 가마의 상태를 관리합니다.
가마는 구조체 2차원 배열입니다.
이걸 매개변수로 넘기는게 꽤 복잡합니다.
그래서 2차원 벡터에 가마를 저장합니다.
<코드>
#include <iostream> #include <algorithm> #include <vector> using namespace std; const int INF = 987654321; struct state { int x; char c; }; int n, res = -INF; int visited[10]; state material[10][4][4][4]; vector<vector<state> > map(5, vector<state>(5)); int cal(vector<vector<state>> tmap) { int r = 0, b = 0, g = 0, y=0; for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { char t = tmap[i][j].c; if (t == 'R') { r += tmap[i][j].x; } else if (t == 'B') { b += tmap[i][j].x; } else if (t == 'G') { g += tmap[i][j].x; } else if (t == 'Y') { y += tmap[i][j].x; } } } return 7 * r + 5 * b + 3 * g + 2 * y; } vector<vector<state>> take_material(vector<vector<state>> tmap, int seq ,int pos, int dir) { //material[seq][dir][i][j] int px, py; switch (pos) { case 0: px = 0; py = 0; break; case 1: px = 1; py = 0; break; case 2: px = 0; py = 1; break; case 3: px = 1; py = 1; break; default: break; } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { int y = i + py, x = j + px; tmap[y][x].x += material[seq][dir][i][j].x; if (tmap[y][x].x > 9) { tmap[y][x].x = 9; } else if (tmap[y][x].x < 0) { tmap[y][x].x = 0; } if (material[seq][dir][i][j].c != 'W') { tmap[y][x].c = material[seq][dir][i][j].c; } } } return tmap; } void dfs(int dep, vector<vector<state>> v) { if (dep == 3) { res = max(cal(v), res); return; } //순서, 위치, 방향을 정해야한다. //순서 for (int i = 0; i < n; i++) { if (visited[i] == 1) continue; visited[i] = 1; //위치 for (int j = 0; j < 4; j++) { //방향 for (int k = 0; k < 4; k++) { vector<vector<state>> tmp = take_material(v, i, j, k); dfs(dep+1, tmp); } } visited[i] = 0; } } void make_rotated() { for (int z = 0; z < n; z++) { for (int r = 1; r < 4; r++) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { material[z][r][i][j].x = material[z][r - 1][3 - j][i].x; material[z][r][i][j].c = material[z][r - 1][3 - j][i].c; } } } } } int main() { cin >> n; for (int i = 0; i < n; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { int t; cin >> material[i][0][j][k].x; } } for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { cin >> material[i][0][j][k].c; } } } for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { map[i][j].x = 0; map[i][j].c = 'W'; } } make_rotated(); dfs(0, map); cout << res << '\n'; return 0; }
<느낀 점>
-여러 상태에 대한 완전탐색은 이렇게 하면 되는구나!
-switch문 사용법에 대해 배웠다. break빼먹으면 답 이상하게 나온다!
-벡터의 생성자
vector의 생성자는 첫 인자로 배열의 사이즈, 두 번째로 초기값을 쓴다.
vector<int> arr(5, 0)는 5의 크기, 0의 초기값을 의미하겠다.
이차원 배열의 경우, vector<vector<int>> arr(5, vector<int>(5, 0)) 이렇게 사용하면 되겠다.
반응형'PS' 카테고리의 다른 글
백준 17837번 새로운 게임2 (0) 2020.01.30 백준 17780번 새로운 게임 (0) 2020.01.29 알고스팟 Quantization (0) 2020.01.24 알고스팟 원주율 외우기 PI (0) 2020.01.22 알고스팟 타일링 TILING2 미완 (0) 2020.01.22