728x90
반응형
https://www.acmicpc.net/problem/17822
17822번: 원판 돌리기
반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀
www.acmicpc.net
최종 코드
GitHub - hwayeon351/BEAKJOON-Algorithms: 백준 알고리즘 소스 코드 모음
백준 알고리즘 소스 코드 모음. Contribute to hwayeon351/BEAKJOON-Algorithms development by creating an account on GitHub.
github.com
//
// main.cpp
// BJ17822
//
// Created by 최화연 on 2022/04/25.
//
#include <iostream>
#include <deque>
#include <cstring>
#include <queue>
using namespace std;
int N, M, T;
//circle[i][j] = i번째 원판에 적힌 j번째 수
deque<deque<int>> circles = {{}, };
int visits[51][51] = {0, };
void rotate_circle(int x, int d, int k) {
for (int i=x; i<=N; i+=x) {
//시계
if (d == 0) {
for (int j=0; j<k; j++) {
int num = circles[i].back();
circles[i].pop_back();
circles[i].push_front(num);
}
}
//반시계
else {
for (int j=0; j<k; j++) {
int num = circles[i].front();
circles[i].pop_front();
circles[i].push_back(num);
}
}
}
}
int erase_num(int si, int sj, int num) {
int cnt = 1;
visits[si][sj] = 1;
queue<pair<int, int>> q;
q.push({si, sj});
while (!q.empty()) {
int i = q.front().first;
int j = q.front().second;
q.pop();
if (j == M-1) {
if (circles[i][0] == num && visits[i][0] == 0) {
visits[i][0] = 1;
circles[i][0] = 0;
cnt ++;
q.push({i, 0});
}
if (circles[i][M-2] == num && visits[i][M-2] == 0) {
visits[i][M-2] = 1;
circles[i][M-2] = 0;
cnt ++;
q.push({i, M-2});
}
}
else if (j == 0) {
if (circles[i][1] == num && visits[i][1] == 0) {
visits[i][1] = 1;
circles[i][1] = 0;
cnt ++;
q.push({i, 1});
}
if (circles[i][M-1] == num && visits[i][M-1] == 0) {
visits[i][M-1] = 1;
circles[i][M-1] = 0;
cnt ++;
q.push({i, M-1});
}
}
else {
if (circles[i][j-1] == num && visits[i][j-1] == 0) {
visits[i][j-1] = 1;
circles[i][j-1] = 0;
cnt ++;
q.push({i, j-1});
}
if (circles[i][j+1] == num && visits[i][j+1] == 0) {
visits[i][j+1] = 1;
circles[i][j+1] = 0;
cnt ++;
q.push({i, j+1});
}
}
if (i < N) {
if (circles[i+1][j] == num && visits[i+1][j] == 0) {
visits[i+1][j] = 1;
circles[i+1][j] = 0;
cnt ++;
q.push({i+1, j});
}
}
if (i > 1) {
if (circles[i-1][j] == num && visits[i-1][j] == 0) {
visits[i-1][j] = 1;
circles[i-1][j] = 0;
cnt ++;
q.push({i-1, j});
}
}
}
if (cnt > 1) circles[si][sj] = 0;
return cnt;
}
int main(int argc, const char * argv[]) {
cin >> N >> M >> T;
for (int i=1; i<=N; i++) {
deque<int> circle;
for (int j=1; j<=M; j++) {
int n;
cin >> n;
circle.push_back(n);
}
circles.push_back(circle);
}
int x, d, k;
for (int t=0; t<T; t++) {
cin >> x >> d >> k;
rotate_circle(x, d, k);
memset(visits, 0, sizeof(visits));
int erase_cnt = 0;
int non_cnt = 0;
int sum = 0;
for (int i=1; i<=N; i++) {
for (int j=0; j<M; j++) {
if (visits[i][j] || circles[i][j] == 0) continue;
int num = circles[i][j];
int same = erase_num(i, j, num);
if (same == 1) {
sum += num;
non_cnt ++;
}
else {
sum += same*num;
erase_cnt += same;
}
}
}
if(sum == 0) {
cout << 0 << endl;
return 0;
}
if(erase_cnt == 0) {
double average = (double)sum/double(non_cnt);
for (int i=1; i<=N; i++) {
for (int j=0; j<M; j++) {
if (circles[i][j] == 0) continue;
if (circles[i][j] > average) circles[i][j] --;
else if (circles[i][j] < average) circles[i][j] ++;
}
}
}
}
int answer = 0;
for (int i=1; i<=N; i++) {
for (int j=0; j<M; j++) {
answer += circles[i][j];
}
}
cout << answer << endl;
return 0;
}
풀이 과정
풀이 시간 1시간 33분
#include <iostream>
#include <deque>
#include <cstring>
#include <queue>
using namespace std;
int N, M, T;
//circle[i][j] = i번째 원판에 적힌 j번째 수
deque<deque<int>> circles = {{}, };
int visits[51][51] = {0, };
void rotate_circle(int x, int d, int k) {
for (int i=x; i<=N; i+=x) {
//시계
if (d == 0) {
for (int j=0; j<k; j++) {
int num = circles[i].back();
circles[i].pop_back();
circles[i].push_front(num);
}
}
//반시계
else {
for (int j=0; j<k; j++) {
int num = circles[i].front();
circles[i].pop_front();
circles[i].push_back(num);
}
}
}
}
int erase_num(int si, int sj, int num) {
int cnt = 1;
visits[si][sj] = 1;
queue<pair<int, int>> q;
q.push({si, sj});
while (!q.empty()) {
int i = q.front().first;
int j = q.front().second;
q.pop();
if (j == M-1) {
if (circles[i][0] == num && visits[i][0] == 0) {
visits[i][0] = 1;
circles[i][0] = 0;
cnt ++;
q.push({i, 0});
}
if (circles[i][M-2] == num && visits[i][M-2] == 0) {
visits[i][M-2] = 1;
circles[i][M-2] = 0;
cnt ++;
q.push({i, M-2});
}
}
else if (j == 0) {
if (circles[i][1] == num && visits[i][1] == 0) {
visits[i][1] = 1;
circles[i][1] = 0;
cnt ++;
q.push({i, 1});
}
if (circles[i][M-1] == num && visits[i][M-1] == 0) {
visits[i][M-1] = 1;
circles[i][M-1] = 0;
cnt ++;
q.push({i, M-1});
}
}
else {
if (circles[i][j-1] == num && visits[i][j-1] == 0) {
visits[i][j-1] = 1;
circles[i][j-1] = 0;
cnt ++;
q.push({i, j-1});
}
if (circles[i][j+1] == num && visits[i][j+1] == 0) {
visits[i][j+1] = 1;
circles[i][j+1] = 0;
cnt ++;
q.push({i, j+1});
}
}
if (i < N) {
if (circles[i+1][j] == num && visits[i+1][j] == 0) {
visits[i+1][j] = 1;
circles[i+1][j] = 0;
cnt ++;
q.push({i+1, j});
}
}
if (i > 1) {
if (circles[i-1][j] == num && visits[i-1][j] == 0) {
visits[i-1][j] = 1;
circles[i-1][j] = 0;
cnt ++;
q.push({i-1, j});
}
}
}
if (cnt > 1) circles[si][sj] = 0;
return cnt;
}
int main(int argc, const char * argv[]) {
cin >> N >> M >> T;
for (int i=1; i<=N; i++) {
deque<int> circle;
for (int j=1; j<=M; j++) {
int n;
cin >> n;
circle.push_back(n);
}
circles.push_back(circle);
}
int x, d, k;
for (int t=0; t<T; t++) {
cin >> x >> d >> k;
rotate_circle(x, d, k);
memset(visits, 0, sizeof(visits));
int erase_cnt = 0;
int non_cnt = 0;
int sum = 0;
for (int i=1; i<=N; i++) {
for (int j=0; j<M; j++) {
if (visits[i][j] || circles[i][j] == 0) continue;
int num = circles[i][j];
int same = erase_num(i, j, num);
if (same == 1) {
sum += num;
non_cnt ++;
}
else {
sum += same*num;
erase_cnt += same;
}
}
}
if(sum == 0) {
cout << 0 << endl;
return 0;
}
if(erase_cnt == 0) {
double average = (double)sum/double(non_cnt);
for (int i=1; i<=N; i++) {
for (int j=0; j<M; j++) {
if (circles[i][j] == 0) continue;
if (circles[i][j] > average) circles[i][j] --;
else if (circles[i][j] < average) circles[i][j] ++;
}
}
}
}
int answer = 0;
for (int i=1; i<=N; i++) {
for (int j=0; j<M; j++) {
answer += circles[i][j];
}
}
cout << answer << endl;
return 0;
}
이전 풀이
풀이 시간 1시간 9분
#include <iostream>
#include <deque>
using namespace std;
int N, M, T;
//board[i][j] = i번째 원판에 적힌 j번째 값
int board[50][50] = {0, };
struct Command{
int x;
int d;
int k;
};
deque<Command> cmds;
Command cmd;
int answer = 0;
void rotate(){
//원판을 회전할 때 사용할 덱
deque<int> x_board;
//인접한 같은 수를 가진 위치들을 저장할 덱
deque<pair<int, int>> erase;
while(!cmds.empty()){
cmd = cmds.front();
cmds.pop_front();
//1. x 배수의 원판을 회전시킨다
for(int x=cmd.x-1; x<N; x+=cmd.x){
x_board.clear();
//현재 원판의 값을 x_board에 담아준다
for(int j=0; j<M; j++){
x_board.push_back(board[x][j]);
}
//시계방향 회전
if(cmd.d == 0){
//k번 뒤에 있는 값을 맨 앞으로 옮긴다
for(int k=0; k<cmd.k; k++){
int temp = x_board.back();
x_board.pop_back();
x_board.push_front(temp);
}
}
//반시계방향 회전
else{
//k번 앞에 있는 값을 맨 뒤로 옮긴다
for(int k=0; k<cmd.k; k++){
int temp = x_board.front();
x_board.pop_front();
x_board.push_back(temp);
}
}
//회전한 값을 원판에 넣어준다
for(int j=0; j<M; j++){
board[x][j] = x_board[j];
}
}
//2. 인접한 값을 탐색한다
erase.clear();
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
if(board[i][j] == 0) continue;
if(j < M-1){
//현재 칸의 값이 다음 칸의 값과 같은 경우, erase에 위치 값을 담는다
if(board[i][j] == board[i][j+1]){
erase.push_back({j, i});
erase.push_back({j+1, i});
//인접한 원판 값과 같은 경우, erase에 위치 값을 담는다
if(i < N-1){
if(board[i][j] == board[i+1][j]){
erase.push_back({j, i+1});
}
}
}
else if(i < N-1){
//인접한 원판 값과 같은 경우, erase에 위치 값을 담는다
if(board[i][j] == board[i+1][j]){
erase.push_back({j, i});
erase.push_back({j, i+1});
}
}
}
else {
if(i < N-1){
//인접한 원판 값과 같은 경우, erase에 위치 값을 담는다
if(board[i][j] == board[i+1][j]){
erase.push_back({j, i});
erase.push_back({j, i+1});
}
}
//현재 칸의 값이 다음 칸의 값과 같은 경우, erase에 위치 값을 담는다
if(board[i][j] == board[i][0]){
erase.push_back({j, i});
erase.push_back({0, i});
}
}
}
}
//2-1. 인접하면서 같은 수를 가진 것이 있는 경우, 지운다
if(erase.size() > 0){
for(int i=0; i<erase.size(); i++){
board[erase[i].second][erase[i].first] = 0;
}
}
//2-2. 지울 것이 없는 경우
else{
//원판의 모든 값의 합을 구한다
int cnt = 0;
int sum = 0;
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
if(board[i][j] == 0) continue;
sum += board[i][j];
cnt++;
}
}
//모든 원판의 값이 0인 경우, while문을 빠져나온다
if(sum == 0){
answer = 0;
break;
}
double avg = (double)sum/cnt;
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
if(board[i][j] == 0) continue;
//원판의 평균값보다 작은 경우, 값을 1 더한다
if(board[i][j] < avg) board[i][j]++;
//원판의 평균값보다 큰 경우, 값을 1 뺀다
else if(board[i][j] > avg) board[i][j] --;
}
}
}
//3. 원판의 모든 값의 합을 answer에 갱신한다
answer = 0;
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
if(board[i][j] == 0) continue;
answer += board[i][j];
}
}
//원판의 모든 값이 0인 경우, while문을 빠져나간다
if(answer == 0) break;
}
}
int main(int argc, const char * argv[]) {
cin >> N >> M >> T;
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
cin >> board[i][j];
}
}
for(int t=0; t<T; t++){
cin >> cmd.x >> cmd.d >> cmd.k;
cmds.push_back(cmd);
}
rotate();
cout << answer << endl;
return 0;
}
//시간복잡도 = T(T*N*M^2) -> O(N^4), 공간복잡도 = O(N^2)
728x90
반응형
'코테 노트 > 백준' 카테고리의 다른 글
백준 3649 로봇 프로젝트 Python3 (0) | 2021.10.04 |
---|---|
백준 19237 어른 상어 C++ (4) | 2021.10.04 |
백준 3686 성냥개비 Python 3 (0) | 2021.10.02 |
백준 20057 마법사 상어와 토네이도 C++ (0) | 2021.09.16 |
백준 20058 마법사 상어와 파이어스톰 C++ (0) | 2021.09.15 |