개발자 김수진

[백준] 17822. 원판 돌리기 본문

알고리즘/백준

[백준] 17822. 원판 돌리기

김수진장 2020. 10. 6. 15:37

[문제]

 

www.acmicpc.net/problem/17822

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀

www.acmicpc.net

[풀이]

 

시뮬레이션 문제로 조건별로 함수 구현해서 풀었다.

 

먼저 원판의 크기와 상태가 입력으로 주어지고 x,d,k가 입력으로 주어진다. 

x의  배수인 원판을 d ( 0이면 시계, 1이면 반시계) 방향으로 k만큼 회전한다.

 

 

1. 회전

2. 인접하면서 같은 수 0으로 바꿔주기

3. 인접하면서 같은 수가 하나도 없다면 원판 전체 평균 구해서 평균 보다 작은 값은 +1, 큰 값은 -1

 

따라서 rotate 함수에서 원판을 회전시킨다. 

 

그 다음 check 함수에서 인접하면서 같은 수를 0으로 바꿔준다.( 이 때 0은 포함이 안되도록 조심해야 된다.)

dx,dy를 통해 범위 내에 있는 상,하,좌,우를 확인했다.

( 추가로 원판이므로 배열의 첫번째 인덱스와 마지막 인덱스도 같은지 확인해야 된다.)

 

check 함수에서 같은 수가 하나도 없다면 avg 함수에서 원판 전체 평균을 구하고 update( 이 때도 평균 구할 때, 0을 조심)

 

[코드]

 

시간 : 4ms

 

#include <iostream>
#define MAX 51

using namespace std;

int arr[MAX][MAX];
int N,M,T;
int x,d,k;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

void avg()
{
    int total=0;
    int cnt =0;
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=M;j++)
        {
            if(arr[i][j]==0)    continue;
            total+=arr[i][j];
            cnt++;
        }
    }
    
    double average = (double)total/(double)cnt;
    if(average==0 ) return ;
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=M;j++)
        {
            if(arr[i][j]==0)    continue;
            if(arr[i][j] > average) arr[i][j]-=1;
            else if(arr[i][j] < average)    arr[i][j]+=1;
            
        }
    }
}

bool check()
{
    int visited[MAX][MAX]={0,};
    
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=M;j++){
            if(arr[i][j]==0)   continue;
            
            for(int k=0;k<4;k++)
            {
                int nx = i +dx[k];
                int ny = j + dy[k];
                if(nx < 1 || ny < 1 || nx > N || ny > M )   continue;
                
                if(arr[nx][ny] == arr[i][j]){
                    visited[nx][ny]=1;
                    visited[i][j]=1;
                }
            }
            
        }
        if(arr[i][1] == arr[i][M] && arr[i][1] !=0)
        {
            visited[i][1]= 1;
            visited[i][M]=1;
        }

    }

    bool flag = false;
    
    for(int i=1;i<=N;i++)
    {
        for(int j=1;j<=M;j++)
        {
            if(visited[i][j]==1)
            {
                arr[i][j]=0;
                flag=true;
            }
        }
    }
    if(flag == true)    return true;
    else return false;
    
}

void rotate()
{
    for(int i=1;i<=N;i++)
    {
        if(i%x!=0 ) continue;
        
        int tmp[MAX]={0,};
        
        for(int j=1;j<=M;j++){
            
            if(d==0){
                int idx =(j+k)%M;
                if(idx == 0)    idx = M;
                tmp[idx]=arr[i][j];
            }
            else{
                int idx = j-k;
                if(idx <=0 )    idx+=M;
                tmp[idx] = arr[i][j];
            }
        }
        
        for(int j=1;j<=M;j++)   arr[i][j] = tmp[j];
    }
}

int main(void)
{
    
    scanf("%d %d %d",&N,&M,&T);
    
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++)    scanf("%d",&arr[i][j]);
    }
    
    for(int i=0;i<T;i++)
    {
        scanf("%d %d %d",&x,&d,&k);
        
        rotate();
        if(check()==false)  avg();
    }
    
    int total=0;
    
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            total+=arr[i][j];
        }
    }
    printf("%d",total);
    
    return 0;
    
}

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 2003. 수들의 합  (0) 2020.10.07
[백준] 17837. 새로운 게임2  (0) 2020.10.06
[백준]1920. 수 찾기  (0) 2020.10.06
[백준] 1976. 여행가자  (0) 2020.10.02
[백준] 17070. 파이프 옮기기  (0) 2020.10.02