You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
중앙에서 회오리 방향으로 회전하면서 이동한 칸에 있는 수를 룰에 맞추어 주변으로 뿌리는 문제입니다.
🤯 Problem
제 생각에는 연산이 최대 500 * 500 * 13 * 4라고 생각했는데 시간 초과가 납니다... 시간복잡도 계산이 잘못된 것 같아요!
🖥️ code
#include<iostream>
#include<cstring>
#include<limits.h>
#include<algorithm>
#include<vector>
#include<queue>usingnamespacestd;typedef pair<int, int> pii;
typedeflonglong ll;
#defineMAX (510)
#defineMOD (1)
#defineall(x) x.begin(), x.end()
// BFS 및 회오리 방향 이동에 사용됨. 상, 좌, 하, 우 방향int dr[4] = {-1, 0, 1, 0};
int dc[4] = { 0, -1, 0, 1 };
int percentage[13] = { 0, 0, 7, 0, 7, 5, 10, 10, 2, 1, 0, 1, 2 }; // BFS 탐색시 탐색 순서에 따라 마주하게 될 percentage 배열 (BFS로 2번째로 탐색하는 노드는 7%에 해당됨)int amount[13] = {0,}; // 모래 양에 percentage를 적용한 값을 저장할 배열int N, R, C, D, ans; // 격자 크기, 현재 행, 열, 방향, 격자 밖으로 나간 모래 양int area[MAX][MAX], visit[MAX][MAX]; // 격자 모래 정보, BFS에 사용할 방문 확인 배열voidinput(); // 입력 받기voidmove(int n); // 전체적인 프로그램을 담은 함수voidmoveLine(int n); // 한 줄 이동voidgetAmount(int sand); // amount 배열 업데이트 함수voidscatter(); // BFS를 통해 모래 뿌리기intmain() {
ios::sync_with_stdio(0); cin.tie(NULL);
input();
move(1);
cout << ans;
return0;
}
voidinput() {
cin >> N;
R = (N + 4) / 2; // 초기 중앙 위치
C = (N + 4) / 2;
D = 1; // 초기 방향 (좌)for (int r = 2; r < N + 2; ++r)
for (int c = 2; c < N + 2; ++c) cin >> area[r][c]; // 모래 정보 저장
}
voidmove(int n) { // 회오리 방향으로 하나씩 접근if (n == N) { moveLine(N - 1); return; } // 마지막 한 줄moveLine(n); // 한 줄씩 이동moveLine(n);
move(n + 1);
}
voidmoveLine(int n) {
if (n == N) n--;
for (int i = 0; i < n; ++i) {
R += dr[D]; // 한 칸 이동
C += dc[D];
if (!area[R][C]) continue; // 모래가 없으면 continuegetAmount(area[R][C]); // amount 업데이트scatter(); // 모래 뿌리기
area[R][C] = 0; // 모래 뿌리고 현재 위치 모래 없애기
}
D = (D + 1) % 4;
}
voidscatter() {
deque<pii> q = { pii(R,C) }; // BFS를 위한 dequememset(visit, 0, sizeof(visit)); // 방문 정보 초기화
visit[R][C] = 1;
int cnt = 1; // 노드 방문 순서int depth = 2; // 모래 뿌리는데 depth 2번이면 다 탐색됨int out = 0; // 격자 밖으로 나간 모래 양while (!q.empty() && depth--) {
int qsize = q.size();
for (int s = 0; s < qsize; ++s) {
int r = q.front().first; // 현재 위치int c = q.front().second;
q.pop_front();
for (int i = D; i < D + 4; ++i) {
int nr = r + dr[i % 4]; // 현재 위치 기반 다음 위치 후보int nc = c + dc[i % 4];
if (visit[nr][nc]) continue; // 이미 방문한 경우 continue
visit[nr][nc] = 1;
if (nr < 2 || nr >= N+2 || nc < 2 || nc >= N+2) out += amount[cnt]; // 격자 밖으로 나간 경우else area[nr][nc] += amount[cnt]; // 모래 뿌리기
cnt++;
if (cnt == 13) { ans+=out; return; } // 탐색 종료
q.push_back(pii(nr, nc));
}
}
}
}
voidgetAmount(int sand) {
int total = sand;
for (int i = 0; i < 13; ++i) {
amount[i] = sand * percentage[i]/100;
total -= amount[i];
}
amount[1] = total;
}
The text was updated successfully, but these errors were encountered:
📝 Question
백준 20057 마법사 상어와 토네이도
중앙에서 회오리 방향으로 회전하면서 이동한 칸에 있는 수를 룰에 맞추어 주변으로 뿌리는 문제입니다.
🤯 Problem
제 생각에는 연산이 최대 500 * 500 * 13 * 4라고 생각했는데 시간 초과가 납니다... 시간복잡도 계산이 잘못된 것 같아요!
🖥️ code
The text was updated successfully, but these errors were encountered: