안녕하세요.

여행벌입니다.

오늘은 ACM-ICPC 2015 본선 문제인

BOJ 11497 Log Jumping 문제를 다뤄보겠습니다.


[문제해석]

N개의 통나무의 높이가 주어지고 우리는 이 통나무를 동그랗게 배치할 것이다.

이때, 통나무 사이의 높이 차이 중 가장 큰 값이 가장 작게 나올 때, 그 값을 출력하는 알고리즘을 구현하라.

예를 들어, 높이가 2,4,5,7,9 인 5개의 통나무를 가지고 [ 2 - 4 - 5 - 7 - 9 ]로 배치를 하면,

통나무 높이 차이 중 가장 큰 값은, 높이가 2인 통나무와 9인 통나무 사이의 높이 차인 7이 된다.

배치를 바꿔 [7 - 4 - 2 - 5 - 9 ] 로 배치를 하면, 통나무 높이 차이 중 가장 큰 값은 높이가 5인 통나무와 9인 통나무 사이의 높이 차인 4가 된다.

 

[알고리즘설계]

1. 통나무 높이가 주어지면 오름차순으로 sort를 진행한다.

2. n개의 통나무가 주어졌을 때, 높이가 작은 통나무부터 A1, A2, ⋯ , An 이라고 하자.

우리는 높이 차이를 최소화해야 하므로, 비슷한 통나무들끼리 배치해줘야 한다.

따라서 가장 작은 통나무부 A1을 배치하고, 그다음에는 A2, A1, A3 식으로 주변에 배치를 진행할 것이다.

->   A4, A2, A1, A3, A5  ⋯ 형태로 배치한다.

3. 실제로 배치할 필요는 없으므로, 2번의 아이디어를 통해 A1부터 시작해 양 옆에 올 통나무들과의 거리 차를 계속 계산해나가며, 그중 MAX를 저장한다.

#include<iostream>
#include<algorithm>

using namespace std;

int list[10000];

int main(void) {
	int test_Case;
	cin >> test_Case;
	for (int i = 0; i < test_Case; i++) {
		int ninput;
		cin >> ninput;
		for (int j = 0; j < ninput; j++)
			cin >> list[j];
		sort(list, list + ninput);

		int distance = list[2] - list[0];

		if (ninput % 2 == 1) {
			for (int j = 1; j <= ninput - 4; j += 2) {
				if (list[j + 2] - list[j] > distance)
					distance = list[j + 2] - list[j];
				if (list[j + 3] - list[j + 1] > distance)
					distance = list[j + 3] - list[j + 1];
			}
		}
		else {
			for (int j = 1; j <= ninput - 5; j += 2) {
				if (list[j + 2] - list[j] > distance)
					distance = list[j + 2] - list[j];
				if (list[j + 3] - list[j + 1] > distance)
					distance = list[j + 3] - list[j + 1];
			}
			if (list[ninput - 1] - list[ninput - 3] > distance)
				distance = list[ninput - 1] - list[ninput - 3];
		}
		if (i != test_Case - 1)
			cout << distance << "\n";
		else
			cout << distance;
	}
}

Indexing이 까다로워서 실수가 있었지만, 그래도 ACM-ICPC 문제 치고는 쉬운 편인 것 같습니다.


 

 

안녕하세요

여행벌입니다.

오늘은 ACM-ICPC 2015 본선 문제인

BOJ 11592번 3-Primes Problem 문제를 다뤄보도록 하겠습니다.


[문제해석]

7 ~ 1000 사이의 양수가 주어졌을 때, 이 양수를 3개의 소수의 합으로 표현할 수 있다면, 3개의 소수를 출력하고, 아니라면 0을 출력하는 알고리즘을 작성하여라.

 

[알고리즘설계]

1. 에라토스테네스 체를 이용하여 1 ~ 1000 사이의 소수를 먼저 찾는다.

2. 3중 포문을 이용해 주어진 양수(ninput)를 3개의 소수의 합으로 판단할 수 있는지 없는지 판단한다.

* Input 값의 범위가 1000 으로 매우 작다. 따라서, 무식하게 3중 포문을 이용해서 푸는 것이 빠르겠다고 판단하였다.

#include<iostream>

using namespace std;

int main(void) {
	// 에라토스테네스체로 prime부터 찾자.
	bool prime[1001];
	for (int i = 0; i < 1001; i++)
		prime[i] = true;
	for (int i = 2; i * i <= 1000; i++) {
		if (prime[i] == true) {
			for (int j = 2 * i; j <= 1000; j += i) {
				prime[j] = false;
			}
		}
	}

	int test_case;
	cin >> test_case;
	for (int i = 0; i < test_case; i++) {
		int ninput, j , k , l;
		cin >> ninput;
		for (j = 2; j < 1000; j++) {
			for ( k = 2; k < 1000; k++) {
				for ( l = 2; l < 1000; l++) {
					if (j + k + l > ninput)
						break;
					if (prime[j] && prime[k] && prime[l] && j + k + l == ninput){
						cout << j << ' ' << k << ' ' << l << '\n';
						break;
					}
				}
				if (prime[j] && prime[k] && prime[l] && j + k + l == ninput) {
					break;
				}
			}
			if (prime[j] && prime[k] && prime[l] && j + k + l == ninput) {
				break;
			}
		}
		if (prime[j] && prime[k] && prime[l] && j + k + l == ninput) {
			continue;
		}
		else
			cout << 0 << '\n';
	}
	return 0;
}

input이 작아서 문제에 쉽게 접근할 수 있었지만, input이 크다면 접근하기 어려울 것 같다.


 

안녕하세요

여행벌입니다.

오늘은 ACM-ICPC 2016 본선 문제인

BOJ 13567번 ROBOT 문제풀이를 해보겠습니다.


[문제파악]

1. (0,0) 위치에서 시작하여 로봇이 주어진 명령에 따라 이동을 한다.

2. 이동 과정에서 주어진 MAP을 벗어난다면, "-1"을 출력하고 아니라면 로봇의 최종 위치를 출력한다.

 

[알고리즘설계]

1. 현재 로봇의 위치를 x , y 변수에 저장하고, 로봇이 현재 향하고 있는 방향을 direction 변수에 담아주자.

direction 에 0(오) 1(왼) 2(위) 3(아래)를 저장한다.

- TURN 명령은 오른쪽으로 90도 회전, 왼쪽으로 90도 회전 2가지 종류가 있고, direction 변수를 TURN에 맞춰서 새롭게 저장해준다.

- MOVE는 direction이 가리키는 방향으로 이동하며 x , y 변수를 새롭게 저장해준다.

2. 명령을 수행하는 과정에서 MAP을 벗어나는지 체크해주고 벗어난다면 "-1"을 출력하고, 아니라면 명령을 다 수행하고 위치를 출력해준다.

 

[주의할점]

1. 명령을 하나씩 받으면서 로봇을 이동시켜주려 한다면 중간에 MAP을 벗어나는 상황이 생겨도 일단 명령 입력을 다 받아야 하므로 종료하면 안 된다.

따라서, 명령을 다 입력받고 로봇을 이동시키는 것이 더 편하다.

#include<stdio.h>
#include<string.h>

char instruction1[1000][5];
int instruction2[1000];

/* direction 에 0(오) 1(왼) 2(위) 3(아래)를 저장한다.*/
int main(void) {
	int length, ninstruction, x = 0, y = 0, direction = 0;
	scanf("%d %d", &length, &ninstruction);

	for (int i = 0; i < ninstruction; i++) {
		scanf("%s %d", instruction1[i], &instruction2[i]);
	}

	for (int i = 0; i < ninstruction; i++) {
		if (strcmp(instruction1[i], "TURN") == 0) {
			// 왼쪽으로 90도 회전
			if (instruction2[i] == 0) {
				if (direction == 0) {
					direction = 2;
				}
				else if (direction == 1) {
					direction = 3;
				}
				else if (direction == 2) {
					direction = 1;
				}
				else if (direction == 3) {
					direction = 0;
				}
			}
			// 오른쪽으로 90도 회전
			else if (instruction2[i] == 1) {
				if (direction == 0) {
					direction = 3;
				}
				else if (direction == 1) {
					direction = 2;
				}
				else if (direction == 2) {
					direction = 0;
				}
				else if (direction == 3) {
					direction = 1;
				}
			}
		}
		else if (strcmp(instruction1[i], "MOVE") == 0) {
			if (direction == 0) {
				for (int j = 0; j < instruction2[i]; j++) {
					x++;
				}
			}
			else if (direction == 1) {
				for (int j = 0; j < instruction2[i]; j++) {
					x--;
				}
			}
			else if (direction == 2) {
				for (int j = 0; j < instruction2[i]; j++) {
					y++;
				}
			}
			else if (direction == 3) {
				for (int j = 0; j < instruction2[i]; j++) {
					y--;
				}
			}
		}
		if(x < 0 || x > length || y < 0 || y > length){
			printf("%d", -1);
			return 0;
		}
	}
	printf("%d %d", x, y);
	return 0;
}

 

안녕하세요

여행벌입니다.

오늘은 ACM-ICPC 2016 본선 문제인

13565번 Percolation 문제 풀이를 해보겠습니다.


[문제해석]

1. M x N 2차원 지도가 입력으로 들어온다.

2. 0이면 지나갈 수 있고, 1이면 지나갈 수 없다.

3. 위에서부터 시작해 맨 아래에 도달할 수 있는지 판별하는 알고리즘을 구현해라.

 

[알고리즘설계]

1. 입력을 String으로 받아서 Int로 한 글자씩 쪼개서 2차원 int형 배열에 저장해준다.

2. 제일 위에 줄에서 0인 값들을 queue에 저장한다.

3. queue를 이용해 BFS 탐색을 진행하고, BFS 탐색이 끝나기 전에 아래에 도달하면 "YES", 아래에 도달하지 못하고 BFS 탐색이 끝나면 "NO"를 출력한다.

 

#include<iostream>
#include<queue>
#include<string>

int map[1000][1000];
bool visited[1000][1000];

using namespace std;

int main(void) {
	int row, column;
	string input;
	queue<int> x;
	queue<int> y;

	cin >> row >> column;
	
	// 입력을 받고, 시작 점들을 셋팅한다.
	for (int i = 0; i < row; i++) {
		cin >> input;
		for (int j = 0; j < column; j++) {
			map[i][j] = int(input[j] - '0');
			if (i == 0 && map[i][j] == 0) {
				x.push(i);
				y.push(j);
				visited[i][j] = true;
			}
		}
	}
	// BFS 탐색을 하자.
	while (!x.empty() && !y.empty()) {
		// 오른쪽으로 갈 수 있는지 Check 하자.
		if (y.front() != (column - 1) && visited[x.front()][y.front() + 1] == false && map[x.front()][y.front() + 1] == 0) {
			x.push(x.front());
			y.push(y.front() + 1);
			visited[x.front()][y.front() + 1] = true;
		}
		// 왼쪽으로 갈 수 있는지 Check 하자.
		if (y.front() != 0 && visited[x.front()][y.front() - 1] == false && map[x.front()][y.front() - 1] == 0) {
			x.push(x.front());
			y.push(y.front() - 1);
			visited[x.front()][y.front() - 1] = true;
		}
		// 위로 갈 수 있는지 Check 하자.
		if (x.front() != 0 && visited[x.front() - 1][y.front()] == false && map[x.front() - 1][y.front()] == 0) {
			x.push(x.front() - 1);
			y.push(y.front());
			visited[x.front() - 1][y.front()] = true;
		}
		// 아래로 갈 수 있는지 Check 하자.
		if (x.front() != (row - 1) && visited[x.front() + 1][y.front()] == false && map[x.front() + 1][y.front()] == 0) {
			if (x.front() == (row - 2)) {
				cout << "YES";
				return 0;
			}
			x.push(x.front() + 1);
			y.push(y.front());
			visited[x.front() + 1][y.front()] = true;
		}
		x.pop();
		y.pop();
	}
	cout << "NO";
	return 0;
}

문제가 쉬워서 코딩도 금방 할 수 있었지만, 코드에 반성해야 할 부분이 많은 것 같다...

+ Recent posts