Koder / 박성훈
article thumbnail

https://www.acmicpc.net/problem/16927

 

16927번: 배열 돌리기 2

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

 

 

입력으로 들어오는 회전수 R이 터무니없어서

뇌정지가 왔었던 문제.

R이 터무니 없다는 부분에서 MOD연산을 활용해야한다는걸 눈치챌수 있다면

문제를 깔끔하게 해결할 수 있다.

 

입력으로 들어오는 배열을

겉껍질 한줄을 배열로, 그 안쪽 한줄을 배열로,

배열을 한껍질씩 벗겨가면서

도넛 모양의 화살표 고리를 하나의 일직선 배열로 풀어서 저장한다.

 

저장한 배열의 인덱스를 R씩 당겨준 다음, 나머지 연산을 활용해서

배열 범위 바깥으로 벗어나지 않도록 해주고

돌려진 도넛을 다시한번 합쳐서 하나의 배열로 합체해주면

문제를 해결할 수 있다.

 

소스코드가 좀 더럽고 복잡할 수 있다.

 

#include <bits/stdc++.h>
#define Ptr (ptr+shift) % L
using namespace std;

int N,M,R;

int arr[345][345] = {0};
int ans[345][345] = {0};

vector<int> donut[200];

void make_donut(int idx){
	int x = idx;
	int y = idx;
	
	for(int i=y; i<M-y+1; i++){
		donut[idx].push_back(arr[x][i]);
	}
	for(int i=x; i<N-x+1; i++){
		donut[idx].push_back(arr[i][M-y+1]);
	}
	for(int i=M-y+1; i>y; i--){
		donut[idx].push_back(arr[N-x+1][i]);
	}
	for(int i=N-x+1; i>x; i--){
		donut[idx].push_back(arr[i][y]);
	}
	return;
}

void fill_donut(int idx, int shift){
	int x = idx;
	int y = idx;
	int ptr = 0;
	int L = donut[idx].size();
	
	for(int i=y; i<M-y+1; i++){
		ans[x][i] = donut[idx][Ptr];
		ptr++;
	}
	for(int i=x; i<N-x+1; i++){
		ans[i][M-y+1] = donut[idx][Ptr];
		ptr++;
	}
	for(int i=M-y+1; i>y; i--){
		ans[N-x+1][i] = donut[idx][Ptr];
		ptr++;
	}
	for(int i=N-x+1; i>x; i--){
		ans[i][y] = donut[idx][Ptr];
		ptr++;
	}
	return;
}


int main(){
	cin.sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	
	cin >> N >> M >> R;
	for(int i=1; i<=N; i++){
		for(int j=1; j<=M; j++){
			cin >> arr[i][j];
		}
	}
	
	int K = min(N/2, M/2);
	
	for(int i=1; i<=K; i++) make_donut(i);
	for(int i=1; i<=K; i++) fill_donut(i, R);
	
	for(int i=1; i<=N; i++){
		for(int j=1; j<=M; j++){
			cout << ans[i][j] << " ";
		}
		cout << "\n";
	}
	return 0;
}

반응형