https://www.acmicpc.net/problem/23288
23288번: 주사위 굴리기 2
크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다. 가장 왼
www.acmicpc.net
나머지 예제 생략
문제 이해
1. 주사위를 이동방향으로 움직인다. 없으면 (맵 밖으로 튀어나가면) 반대 방향으로 이동한다.
2. 도착한 데에서 점수 획득한다,
- 동서남북으로 이동할 수 있는 칸의 수를 구해야 한다. 즉, BFS를 하면서 최대 거리(C)를 구하면 된다.
- 그리고 나머지는 하라는 대로 계산하면 되다.
3. 이동방향을 결정하는데, dice.bottom과 map[y][x] 를 비교해서 결정하면 된다.
주사위를 이동하는 것만 잘 정의하면 된다. (Move())
주사위를 다음과 같이 보고 구조체를 초기화한다
각 방향으로 움직일 때 이 구조체가 어떻게 바뀌는지를 보면
이제 정해졌으니까 이대로 Move()에 구현하면 된다.
작성 코드
#if 1
#include <stdio.h>
#include <string.h>
#define MAXN 20
#define EAST 0
#define SOUTH 1
#define WEST 2
#define NORTH 3
int N, M, K;
int map[MAXN + 5][MAXN + 5];
int visited[MAXN + 5][MAXN + 5];
int pnt;
struct dicest {
int bottom;
int up;
int east;
int west;
int north;
int south;
} dice;
int diceY, diceX, diceD;
int dy[] = { 0, 1, 0, -1 }; // 동, 남, 서, 북
int dx[] = { 1, 0, -1, 0 };
int reverse[] = { WEST, NORTH, EAST, SOUTH };
void Get_Input(void) {
scanf("%d %d %d", &N, &M, &K);
for (int i = 1; i <= N; i++) {
for(int j = 1; j<=M; j++){
scanf("%d", &map[i][j]);
}
}
}
void Init(void) {
dice.bottom = 6;
dice.up = 1;
dice.east = 3;
dice.west = 4;
dice.north = 5;
dice.south = 2;
diceX = 1;
diceY = 1;
diceD = 0;
}
void Move(void) {
int nEast, nWest, nSouth, nNorth, nBottom, nUp;
int ny, nx;
// diceD 방향으로 움직인다
ny = dy[diceD] + diceY;
nx = dx[diceD] + diceX;
if (ny < 1 || ny > N || nx < 1 || nx > M) {
// 칸이 없다면 방향 반대로
diceD = reverse[diceD];
ny = dy[diceD] + diceY;
nx = dx[diceD] + diceX;
}
diceY = ny, diceX = nx;
if (diceD == EAST) {
nBottom = dice.east;
nUp = dice.west;
nWest = dice.bottom;
nEast = dice.up;
dice.west = nWest, dice.east = nEast;
dice.bottom = nBottom, dice.up = nUp;
}
if (diceD == WEST) {
nBottom = dice.west;
nUp = dice.east;
nWest = dice.up;
nEast = dice.bottom;
dice.west = nWest, dice.east = nEast;
dice.bottom = nBottom, dice.up = nUp;
}
if (diceD == SOUTH) {
nBottom = dice.north;
nUp = dice.south;
nSouth = dice.bottom;
nNorth = dice.up;
dice.north = nNorth, dice.south = nSouth;
dice.bottom = nBottom, dice.up = nUp;
}
if (diceD == NORTH) {
nBottom = dice.south;
nUp = dice.north;
nNorth = dice.bottom;
nSouth = dice.up;
dice.north = nNorth, dice.south = nSouth;
dice.bottom = nBottom, dice.up = nUp;
}
}
// queue
typedef struct ele {
int y;
int x;
}ELE;
ELE q[MAXN * MAXN * 10];
int wp, rp;
void enq(int y, int x) { q[wp].y = y; q[wp++].x = x; }
ELE deq(void) { return q[rp++]; }
int empty(void) { return wp == rp; }
int BFS(int sy, int sx) {
// 초기화
memset(visited, 0, sizeof(visited));
wp = 0, rp = 0;
int cnt = 1;
int no = map[sy][sx];
visited[sy][sx] = 1;
enq(sy, sx);
while (!empty()) {
ELE cur = deq();
for (int i = 0; i < 4; i++) {
int ny = dy[i] + cur.y;
int nx = dx[i] + cur.x;
if (ny < 1 || ny > N || nx < 1 || nx > M) continue;
if (map[ny][nx] != no) continue;
if (visited[ny][nx] > 0) continue;
visited[ny][nx] = 1;
enq(ny, nx);
cnt++;
}
}
return cnt;
}
void Earn_Point(void) {
int c = BFS(diceY, diceX);
pnt += map[diceY][diceX] * c;
}
void Change_Direction(void) {
int a = dice.bottom;
int b = map[diceY][diceX];
if (a > b) diceD = (diceD + 1) % 4;
if (a < b) diceD = (diceD - 1 < 0) ? 3 : diceD - 1;
}
int main(void) {
freopen("in.txt", "r", stdin);
Get_Input();
Init();
for (int k = 0; k < K; k++) {
Move(); // 굴러감
Earn_Point(); // 점수 획득
Change_Direction(); // 방향 전환
}
printf("%d", pnt);
return 0;
}
#endif
'컴퓨터기본 > 문제풀이' 카테고리의 다른 글
[백준] 17142번: 연구소 3 (0) | 2021.11.21 |
---|---|
[백준] 23289번: 온풍기 안녕! (0) | 2021.11.20 |
[백준] 20061번: 모노미노도미노2 (0) | 2021.11.20 |
[백준] 19238번: 스타트 택시 (0) | 2021.11.20 |
[백준] 19237번: 어른 상어 (0) | 2021.11.20 |