반응형

문제링크:www.acmicpc.net/problem/20057

 

20057번: 마법사 상어와 토네이도

마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을

www.acmicpc.net

 

20년도 하반기 삼성 코딩테스트 기출문제입니다.

저는 오전에 풀어서 접하지 못했던 문제입니다. 

 

우선 크게 구현해야하는 부분이 4가지 였습니다.

  • 1. 입력 받기
  • 2. 회전시키기
  • 3. 모래 이동
  • 4. 결과 도출

2, 3번이 핵심입니다.

 

우선 회전은 for문과 y_ar, x_ar(방향배열)을 통해서 구현했습니다.

가운데 점부터 시작하여 방향별로 cnt 갯수만큼 점을 옮겨줌으로서 2번 회전을 구현했습니다.

 

그렇다면 3번 모래 이동은 어떤식으로 구현할까요?

저는 구조체를 하나 생성했습니다.

typedef struct a {
	vector <int> vec;
	double per;

}moved;

해당 구조체에 vec에는 모래가 이동하는 좌표로 가기위해 필요 값들을 그리고 per에는 해당 좌표에 대한 퍼센트를 기입해놓았습니다. 현재 방향에 따라서 값을 더해주는 형태로 구현했기 때문에 아래처럼 간단하게 구현할 수 있었습니다.

 

 

아래는 정답코드입니다. 해당 문제에서 주의할 점은 수의 범위가 넘어갈 때에는 예외처리를 통해서 데이터를 지우게끔 해야하는 것입니다. 

#include <iostream>
#include <vector>
using namespace std;

typedef struct a {
	vector <int> vec;
	double per;

}moved;

int n = 0, result =0;
int arr[501][501] = { 0, };
moved val[9];
int y_ar[4] = { 0,1,0,-1 };
int x_ar[4] = { -1,0,1,0 };

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	//init
	val[0].vec.push_back(1), val[0].per = 0.01;
	val[1].vec.push_back(3), val[1].per = 0.01;
	val[2].vec.push_back(1), val[2].vec.push_back(0), val[2].per = 0.07;
	val[3].vec.push_back(3), val[3].vec.push_back(0), val[3].per = 0.07;
	val[4].vec.push_back(1), val[4].vec.push_back(1), val[4].vec.push_back(0), val[4].per = 0.02;
	val[5].vec.push_back(3), val[5].vec.push_back(3), val[5].vec.push_back(0), val[5].per = 0.02;
	val[6].vec.push_back(1), val[6].vec.push_back(0), val[6].vec.push_back(0), val[6].per = 0.1;
	val[7].vec.push_back(3), val[7].vec.push_back(0), val[7].vec.push_back(0), val[7].per = 0.1;
	val[8].vec.push_back(0), val[8].vec.push_back(0), val[8].vec.push_back(0), val[8].per = 0.05;
	//0.
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			cin >> arr[i][j];
			result += arr[i][j];
		}
	
	//1. rotate
	int cy = n / 2 + 1, cx = n / 2 + 1, dir = 0, cnt = 0;
	for (int k = 0; k < n * 2 - 1; k++) {
		if (k % 2 == 0)
			cnt++;
		for (int i = 0; i < cnt; i++) { // 해당방향으로 이동
			int curval = arr[cy + y_ar[dir]][cx + x_ar[dir]];

			for (int j = 0; j < 9; j++) {
				int ny = cy;
				int nx = cx;
				for (int u = 0; u < val[j].vec.size(); u++) {
					ny += y_ar[(dir + val[j].vec[u]) % 4];
					nx += x_ar[(dir + val[j].vec[u]) % 4];
				}
				if (ny >= 1 && ny <= n && nx >= 1 && nx <= n) {
					arr[ny][nx] += (int)(curval * val[j].per);
				}
				arr[cy + y_ar[dir]][cx + x_ar[dir]] -= (int)(curval * val[j].per);

			}
			//알파 계산 
			if (cy + y_ar[dir] * 2 >= 1 && cy + y_ar[dir] * 2 <= n && cx + x_ar[dir] * 2 >= 1 && cx + x_ar[dir] * 2 <= n) 
				arr[cy + y_ar[dir] * 2][cx + x_ar[dir] * 2] += arr[cy + y_ar[dir]][cx + x_ar[dir]];
			
			if(cy + y_ar[dir] >= 1 && cy + y_ar[dir] <= n && cx + x_ar[dir] >= 1 && cx + x_ar[dir] <= n)
				arr[cy + y_ar[dir]][cx + x_ar[dir]] = 0;

			cy += y_ar[dir], cx += x_ar[dir]; // 실제 좌표 이동

			/*
			cout << endl;
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= n; j++)
					cout << arr[i][j] << ' ';
				cout << endl;
			}*/
		}
		
		dir++;
		if (dir == 4)
			dir = 0;

		
	}





	int sum = 0;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) 
			sum += arr[i][j];	
	result -= sum;
	cout << result << endl;
	return 0;
}
반응형

+ Recent posts