반응형

문제출처

https://programmers.co.kr/learn/courses/30/lessons/64065

 

코딩테스트 연습 - 튜플

"{{2},{2,1},{2,1,3},{2,1,3,4}}" [2, 1, 3, 4] "{{1,2,3},{2,1},{1,2,4,3},{2}}" [2, 1, 3, 4] "{{4,2,3},{3},{2,3,4,1},{2,3}}" [3, 2, 4, 1]

programmers.co.kr

 

문제풀이

1. ",{" 기준으로 문자열을 잘라 집합을 구한 후 집합의 크기를 기준으로 정렬한다.
2.  i번째 집합에 속해있는 숫자묶음을 추출한뒤 answer 리스트에 없는 숫자만 추가해주면 된다.


c++로 풀면 꽤나 소스도 길어지고 빡빡했을거 같았다. 왜냐하면 숫자가 아닌 문자들을 다 제외하는 로직을 구현을 시작해야 해서 이참에 파이썬을 한번 써봤다.
왜 문자열은 파이썬을 사용하면 금방 풀 수 있다고 하는지 느꼈다.
문자열 문제에 항상 힘들어했는데 파이썬을 애용해봐야겠다

 

 

소스코드

https://github.com/sw93/algorithm/blob/master/Programmers/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4%20-%20%ED%8A%9C%ED%94%8C.py

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

 

import re

def solution(s):
    answer = [] # 정답
    numberSet = s.split(',{') # 집합을 구함
    numberSet.sort(key = len) # 집합 크기를 기준으로 정렬

    for i in numberSet :
    	number = re.findall("\d+", i) # 숫자묶음을 추출
    	for j in number :
    		if int(j) not in answer :
    			answer.append(int(j))
    return answer
반응형

'Algorithm' 카테고리의 다른 글

[BOJ 2178] 미로 탐색  (0) 2020.05.18
[BOJ 4963] 섬의 개수  (0) 2020.05.18
[BOJ 1107] 리모컨  (0) 2020.05.15
[BOJ 3085] 사탕 게임  (0) 2020.05.14
[BOJ 17143] 낚시왕  (0) 2020.05.13
반응형

문제출처

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

 

1107번: 리모컨

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다.  둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼��

www.acmicpc.net

 

문제풀이

완전탐색 문제인데 약간 생각할 부분이 있었다. n의 범위가 50만까지인데 채널은 무한이기 때문에 뒤에서 탐색하는 경우 버튼을 더 적게 누를수도 있기 때문이다. 또 숫자버튼을 누르고 + 또는 -버튼 1개만 계속 눌러야 한다. 왜냐하면 +버튼을 누르다 -버튼을 누르고 다시 +버튼을 누르면 중복이 발생하기 때문에 최소값이 될 수 없기 때문이다.

이후 단순 구현만 해주면 된다.

 

소스코드

https://github.com/sw93/algorithm/blob/master/BOJ_PS/BOJ_1107/boj1107.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

 

#include <iostream>
#include <algorithm>
using namespace std;
int n, m;
bool brokenButton[10];

// 숫자버튼을 누른 채널으로 이동 가능한지 확인하는 함수
bool checkButton(int channel) {
	if (channel == 0) {
		if (brokenButton[0]) return false;
		else return true;
	}
	while (channel) {
		if (brokenButton[channel % 10]) return false;
		else channel /= 10;
	}
	return true;
}

// checkButton을 통과한 채널의 자릿수를 구하는 함수
int getChannelDigit(int channel) {
	int ret = 0;
	if (channel == 0) return 1;
	while (channel) {
		channel /= 10;
		ret++;
	}
	return ret;
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	cin >> n >> m;
	int buttonNumber;
	for (int i = 0; i < m; i++) {
		cin >> buttonNumber;
		brokenButton[buttonNumber] = 1;
	}

	int ans = 987654321;

	// 뒤에서 탐색하는게 더 효과적인 경우도 있으므로 n의 범위를 2배 늘림
	// 예를 들어 6버튼만 안고장나고 60만번 채널로 이동하고 싶은 경우
	// 초기 100번 채널에서 +버튼만 누르는 것 보다 666,666채널에서 -버튼을 누르는 횟수가 더 적음
	for (int i = 0; i <= 1000000; i++) {
		int channel = i;
		if (checkButton(channel)) {

			// 숫자버튼을 눌러 이동할때 필요한 자릿수
			int digit = getChannelDigit(channel);

			// 숫자버튼 이동과 +버튼 또는 -버튼 클릭의 합을 비교
			ans = min(ans, digit + abs(n - channel));
		}
	}

	cout << min(ans, abs(n - 100));
	return 0;
}
반응형

'Algorithm' 카테고리의 다른 글

[BOJ 4963] 섬의 개수  (0) 2020.05.18
[프로그래머스 64065] 튜플  (0) 2020.05.15
[BOJ 3085] 사탕 게임  (0) 2020.05.14
[BOJ 17143] 낚시왕  (0) 2020.05.13
[BOJ 17779] 게리맨더링2  (0) 2020.05.12
반응형

문제 출처

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

 

3085번: 사탕 게임

문제 상근이는 어렸을 적에 "봄보니 (Bomboni)" 게임을 즐겨했다. 가장 처음에 N×N크기에 사탕을 채워 놓는다. 사탕의 색은 모두 같지 않을 수도 있다. 상근이는 사탕의 색이 다른 인접한 두 칸을 고

www.acmicpc.net

 

문제 풀이

모든 경우의 수를 다 탐색하는 문제다. 위치마다 4방향 탐색을 해도 되지만 위쪽과 왼쪽은 조금만 생각해보면 중복되는 처리임을 알 수 있다.

시간 복잡도는 사탕의 위치를 바꾸는 데 2방향(오른쪽, 아래)과 n의 크기로 구하는데 2 X 50 X 50 , 최대 개수를 구하는데는 50 X 50이다. 따라서 2 X 50^4 = 12,500,000으로 1초 안에 풀이가 가능하다.

즉 O(N^4)의 시간 복잡도를 가진 이 알고리즘은 N이 50이하로 작게 제한되어 있기 때문에 완전 탐색을 해도 충분히 풀이할 수 있다고 판단했다.

 

소스 코드

https://github.com/sw93/algorithm/blob/master/BOJ_PS/BOJ_3085/boj3085.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

 

#include <iostream>
#include <algorithm>
using namespace std;
int n;
char map[50][50];
void init() {
	cin >> n;
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {
			cin >> map[y][x];
		}
	}
}
int eatCandy() {
	int ret = 1;

	// 열 체크
	for (int y = 0; y < n; y++) {
		int count = 1;
		for (int x = 1; x < n; x++) {
			if (map[y][x] == map[y][x - 1]) count++;
			else count = 1;
			ret = max(count, ret);
		}
	}

	// 행 체크
	for (int x = 0; x < n; x++) {
		int count = 1;
		for (int y = 1; y < n; y++) {
			if (map[y][x] == map[y - 1][x]) count++;
			else count = 1;
			ret = max(count, ret);
		}
	}

	return ret;
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	init();
	int ans = 0;
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {

			// 오른쪽 탐색
			if (x + 1 < n) {
				swap(map[y][x], map[y][x + 1]);
				ans = max(ans, eatCandy());
				swap(map[y][x], map[y][x + 1]);
			}

			// 아래쪽 탐색
			if (y + 1 < n) {
				swap(map[y][x], map[y + 1][x]);
				ans = max(ans, eatCandy());
				swap(map[y][x], map[y + 1][x]);
			}
		}
	}
	cout << ans;
	return 0;
}
반응형

'Algorithm' 카테고리의 다른 글

[프로그래머스 64065] 튜플  (0) 2020.05.15
[BOJ 1107] 리모컨  (0) 2020.05.15
[BOJ 17143] 낚시왕  (0) 2020.05.13
[BOJ 17779] 게리맨더링2  (0) 2020.05.12
[프로그래머스 17678 - 카카오 2018 1차] 셔틀 버스  (0) 2020.05.06
반응형

문제출처

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

 

17143번: 낚시왕

낚시왕이 상어 낚시를 하는 곳은 크기가 R×C인 격자판으로 나타낼 수 있다. 격자판의 각 칸은 (r, c)로 나타낼 수 있다. r은 행, c는 열이고, (R, C)는 아래 그림에서 가장 오른쪽 아래에 있는 칸이다.

www.acmicpc.net

 

문제풀이

 

처음에 시간복잡도를 생각 안하고 구현했더니 시간초과가 났다. 다음부터는 문제풀이 이전에 꼭 시간복잡도를 먼저 계산하고 풀이해야겠다.

 

이 문제는 상어의 정보가 주어지고 낚시왕이 왼쪽에서 오른쪽으로 이동하면서 잡은 상어의 크기의 총 합을 출력하는 문제이다.

문제에서 요구하는 구현사항은 2가지인데 순서에 맞게 구현해줘야 한다.

 

나 같은 경우는 낚시왕이 (0, 0)에서 시작해 x축 이동을 하면서 1번을 구현했다.

 

2번 조건을 구현하기 위해 catchShark(int x) 함수를 만들었다.

catchShark(int x) 함수

낚시왕이 위치한 x좌표를 넘겨줘서 y축 탐색을 해 가장 가까운 상어를 잡는 함수이다.

int catchShark(int x) {
	int ret = 0;
	for (int y = 1; y <= r; y++) {
		if (map[y][x] != 0) {
			ret = v[map[y][x]].z;
			v[map[y][x]].dead = 1;
			map[y][x] = 0;

			break;
		}
	}
	return ret;
}

 

3번 조건이 가장 까다로웠다. 이 조건은 moveShark() 함수를 만들었다.

moveShark() 함수

살아있는 상어 수만큼 반복하면서 상어 좌표를 이동해주는 함수이다. 행 처리와 열 처리가 같기 때문에 열 처리를 기준으로 설명하겠습니다.

여기서 가장 중요한게 speed = speed % ((c - 1) * 2) 부분인데 이 처리를 하지 않으면 시간초과가 납니다.

만약 r=4, c=6인 경우 상어가 방향전환을 하고 움직일때 1번 열과 6번 열은 1번씩만 자리잡고 2, 3, 4, 5번 열은 2번씩 자리잡는다. 

 

빨간 색을 1번만 위치하는 열이고 파랑색은 기존 위치 초록색을 방향전환을 했을때 자리잡는 위치이다. 이 표를 가지고 시뮬레이션을 해보면 규칙을 파악할 수 있다. 이 규칙을 이용해서 반복횟수를 줄여 시간초과를 벗어나면 된다.

 

이후 조건에 따라 구현해줬다. 상어가 이동한 자리가 빈칸이면 상어 번호를 map에 저장하고 움직인 상어가 위치한다면 크기를 비교해 먹거나 먹히도록 구현했다. 움직이지 않은 상어가 위치하는 경우는 반복문을 통해 나중에 처리하기 때문에 현재 위치한 상어를 위치시키면 된다.

 

void moveShark() {
	for (int i = 1; i <= m; i++) {

		// 죽은 상어는 건너뛴다
		if (v[i].dead) continue;

		// 움직일 상어 정보
		int y = v[i].r;
		int x = v[i].c;
		int speed = v[i].s;
		int dir = v[i].d;
		int size = v[i].z;

		// 현재 움직일 상어 기존 위치 초기화
		if (map[y][x] == i) map[y][x] = 0;

		// 위, 아래
		if (dir == 0 || dir == 1) {
			speed = speed % ((r - 1) * 2);
			
			while (speed--) {
				int ny = y + dy[dir];
				if (1 > ny || ny > r) dir = 1 - dir;
				y += dy[dir];
			}
		} 
		
		// 오른쪽 왼쪽
		else { 
			speed = speed % ((c - 1) * 2);

			while (speed--) {
				int nx = x + dx[dir];
				if (1 > nx || nx > c) dir = 5 - dir;
				x += dx[dir];
			}
		}

		// 이동한 상어 위치 최신화
		v[i].r = y;
		v[i].c = x;
		v[i].d = dir;

		// 이동한 위치가 빈칸인 경우 => 위치 이동
		if (map[y][x] == 0) {
			map[y][x] = i;
		} 

		// 이동한 위치에 이미 이동을 완료한 상어가 있는 경우 => 잡아먹거나 잡아 먹힘
		else if (i > map[y][x]) { 

			// 이동한 상어의 사이즈가 더 큰 경우
			if (size > v[map[y][x]].z) {
				v[map[y][x]].dead = 1;
				map[y][x] = i;
			}

			// 이동한 상어의 사이즈가 더 작은 경우 
			else {
				v[i].dead = 1;
			}
		} 
		
		// 이동한 위치에 아직 이동 안 한 상어가 있는 경우 => 이후에 재 처리하기 때문에 뒤집어 씌움
		else { 
			map[y][x] = i;
		}
	}
}

 

기존에 시간초과했던 방법 즉, 문제대로 그냥 구현한 방법의 시간복잡도는 다음과 같다.

상어의수(10000) X 속도(1000) X 낚시왕이 움직이는 열의 수(100) 

= 10^4 * 10^3 * 10^2 = 10^9 = 1,000,000,000 (10억) 번의 연산이 필요하다.

1초에 1억번 계산가능하다는 가정하에 이 문제는 단순 구현으로는 1초안에 해결할 수 없다.

 

시간 초과때문에 힘들었던 문제인데 진짜 시간복잡도를 먼저 계산하는게 왜 중요한지 다시 깨우친 문제이다. 시험장에서였으면 아마 시간초과로 탈락했을거 같다.

 

소스코드

https://github.com/sw93/algorithm/blob/master/SW_TEST(samsung)/BOJ_17143/boj17143.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

 

#include <iostream>
#include <vector>
using namespace std;
struct SHARK {
	int r, c, s, d, z;
	bool dead;
};
int r, c, m;
int map[101][101];
const int dy[] = { -1, 1, 0, 0 };
const int dx[] = { 0, 0, 1, -1 };
vector<SHARK> v;

void init() {
	cin >> r >> c >> m;

	// 1번부터 시작
	v.push_back({ 0,0,0,0,0,0 });
	for (int i = 1; i <= m; i++) {
		SHARK shark;
		cin >> shark.r >> shark.c >> shark.s >> shark.d >> shark.z;
		shark.dead = 0;
		shark.d -= 1;
		v.push_back(shark);
		map[shark.r][shark.c] = i;
	}
}

int catchShark(int x) {
	int ret = 0;
	for (int y = 1; y <= r; y++) {
		if (map[y][x] != 0) {
			ret = v[map[y][x]].z;
			v[map[y][x]].dead = 1;
			map[y][x] = 0;

			break;
		}
	}
	return ret;
}

void moveShark() {
	for (int i = 1; i <= m; i++) {

		// 죽은 상어는 건너뛴다
		if (v[i].dead) continue;

		// 움직일 상어 정보
		int y = v[i].r;
		int x = v[i].c;
		int speed = v[i].s;
		int dir = v[i].d;
		int size = v[i].z;

		// 현재 움직일 상어 기존 위치 초기화
		if (map[y][x] == i) map[y][x] = 0;

		// 위, 아래
		if (dir == 0 || dir == 1) {
			speed = speed % ((r - 1) * 2);
			
			while (speed--) {
				int ny = y + dy[dir];
				if (1 > ny || ny > r) dir = 1 - dir;
				y += dy[dir];
			}
		} 
		
		// 오른쪽 왼쪽
		else { 
			speed = speed % ((c - 1) * 2);

			while (speed--) {
				int nx = x + dx[dir];
				if (1 > nx || nx > c) dir = 5 - dir;
				x += dx[dir];
			}
		}

		// 이동한 상어 위치 최신화
		v[i].r = y;
		v[i].c = x;
		v[i].d = dir;

		// 이동한 위치가 빈칸인 경우 => 위치 이동
		if (map[y][x] == 0) {
			map[y][x] = i;
		} 

		// 이동한 위치에 이미 이동을 완료한 상어가 있는 경우 => 잡아먹거나 잡아 먹힘
		else if (i > map[y][x]) { 

			// 이동한 상어의 사이즈가 더 큰 경우
			if (size > v[map[y][x]].z) {
				v[map[y][x]].dead = 1;
				map[y][x] = i;
			}

			// 이동한 상어의 사이즈가 더 작은 경우 
			else {
				v[i].dead = 1;
			}
		} 
		
		// 이동한 위치에 아직 이동 안 한 상어가 있는 경우 => 이후에 재 처리하기 때문에 뒤집어 씌움
		else { 
			map[y][x] = i;
		}
	}
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	init();

	// 예외 처리
	if (m == 0) {
		cout << 0;
		return 0;
	}

	int ans = 0;
	for (int x = 1; x <= c; x++) {
		ans += catchShark(x);
		moveShark();
	}
	cout << ans;
	return 0;
}
반응형
반응형

문제출처

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

 

17779번: 게리맨더링 2

재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름��

www.acmicpc.net

 

문제풀이

문제를 이해하는데 너무 오래걸렸다. 이해력이 부족한건가..

n X n 배열에서 5개의 선거구를 만들어 선거구의 인구의 최댓값과 최솟값의 차이가 가장 적은 결과를 출력하는 문제이다.

 

이 문제는 가장 중요한게 1, 2, 3, 4번 지구의 경계선을 어떻게 나누는지 이해하는게 가장 중요하다.

처음에 d1과 d2의 값을 어떻게 해야 하는지 고민이 많았는데 문제를 자세히 읽고 1, 2, 3, 4번 꼭지점의 좌표를 적어보면 이해하기 편하다.

 

 

 

1번 : (y, x)

2번 : (y+d2, x+d2)

3번 : (y+d1, x-d1)

4번 : (y+d1+d2, x-d1+d2)

즉, d1은 왼쪽대각선으로 이동하는 칸의 수이고 d2는 오른쪽대각선으로 이동하는 칸의 수임을 유추할 수 있다.

그러면 d1의 범위를 알 수 있다. d1은 3번꼭지점의 x좌표를 기준으로 생각해 보자.

3번 꼭지점의 x-d1은 0이거나 0보다 커야한다. (x-d1 >= 0) 이 식을 d1으로 정리하면 d1<= x의 식이 나온다.

마찬가지로 d2의 범위는 2번 꼭지점의 x좌표를 기준으로 생각해보자. 

x+d2는 마찬가지고 n X n 배열을 벋어날수 없기 때문에 x+d2 <= n의 식이 나오고 정리하면 d2 <= n-x 이다.

 

위와 같이 d1과 d2의 범위를 구하고 전체탐색을 한다. 이때 y, x, d1, d2의 값으로 경계선을 만들 수 없는 경우는 제외한다. 경계선을 만들 수 있으면 꼭지점 정보를 vector에 저장하고 1번 지역구부터 4번 지역구까지 tempMap에 값을 넣어줬다.

 

1번 선거구의 경우 0행부터 3번꼭지점 행-1까지 범위안에 들어와야한다.  열은 0열부터 1번꼭지점까지의 열이다.

이때 그림을 보면 y값(행)이 증가할때 마다 열값이 1개씩 감소하는 것을 알 수 있다. 때문에 y값(행)이 1번꼭지점의 y값보다 크거나 같으면 갯수를 세어 열을 채워줄때 빼줬다. 이후 2, 3, 4번 지역구도 동일하게 진행.

이 부분은 코드를 보는게 더 이해가 빠를듯 하다.

 

이후 n X n 배열을 순회하면서 1~5번의 값을 기준으로 map에 있는 인구수를 벡터에 저장해 오름차순으로 정렬한뒤 차이를 구했다. 이 차이는 경계선이 정상적으로 그려질때의 값이므로 값을 구할때마다 min함수를 이용해 차이를 최신화해줬다.

 

문제를 이해하는게 정말 어려웠다. 처음에 y, x, d1, d2의 부등식을 정리하려고 애썼는데 사실 지금도 어떻게 정리하는지 모르겠다... (혹시 x<x+d1+d2<=n, 1<=y-d1<y<y+d2<=n) 이 식을 정리해서 문제풀이 하신분 댓글 부탁드립니다.

 

삼성기출 문제가 최신문제일수록 좀더 난이도가 생기는 느낌이다. 뭔가 전체탐색을 하면서 시뮬레이션이 섞여있거나 시뮬레이션 조건이 까다로워지는건 나만의 느낌인가....?

 

소스코드

https://github.com/sw93/algorithm/blob/master/SW_TEST(samsung)/BOJ_17779/boj17779.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

 

#include <iostream>
#include <vector>
#include <algorithm>
#define INF 987654321
using namespace std;
int n, ans = INF;
int map[20][20];
int tempMap[20][20];
vector<pair<int, int> > v;
void init() {
	cin >> n;
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {
			cin >> map[y][x];
		}
	}
}
bool checkBoard(int y, int x, int d1, int d2) {

	// 3번 꼭지점
	if (y + d1 >= n || x - d1 < 0) return false;

	// 2번 꼭지점
	if (y + d2 >= n || x + d2 >= n) return false;

	// 4번 꼭지점
	if (y + d1 + d2 >= n || x - d1 + d2 < 0) return false;
	return true;
}
void calc() {
	vector<int> ret(5, 0);
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {
			if (tempMap[y][x] == 1) ret[0] += map[y][x];
			else if (tempMap[y][x] == 2) ret[1] += map[y][x];
			else if (tempMap[y][x] == 3) ret[2] += map[y][x];
			else if (tempMap[y][x] == 4) ret[3] += map[y][x];
			else if (tempMap[y][x] == 5) ret[4] += map[y][x];
		}
	}

	sort(ret.begin(), ret.end());
	int diff = ret[4] - ret[0];
	ans = min(ans, diff);
}
void solve() {

	// 5번 지역구로 모두 초기화 (1, 2, 3, 4번 지역구가 아니면 5번 지역구)
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {
			tempMap[y][x] = 5;
		}
	}

	// 1번 지역구
	int minusCount = 0;
	for (int y = 0; y < v[1].first; y++) {
		if (y >= v[0].first) minusCount++;
		for (int x = 0; x <= v[0].second - minusCount; x++) {
			tempMap[y][x] = 1;
		}
	}

	// 2번 지역구
	minusCount = 0;
	for (int y = 0; y <= v[2].first; y++) {
		if (y > v[0].first) minusCount++;
		for (int x = v[0].second + minusCount + 1; x < n; x++) {
			tempMap[y][x] = 2;
		}
	}

	// 3번 지역구
	minusCount = 0;
	for (int y = n - 1; y >= v[1].first; y--) {
		if (y < v[3].first) minusCount++;
		for (int x = 0; x < v[3].second - minusCount; x++) {
			tempMap[y][x] = 3;
		}
	}

	// 4번 지역구
	minusCount = 0;
	for (int y = n - 1; y > v[2].first; y--) {
		if (y <= v[3].first) minusCount++;
		for (int x = v[3].second + minusCount; x < n; x++) {
			tempMap[y][x] = 4;
		}
	}

	calc();
	v.clear();
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	init();
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {

			// d1 = 왼쪽 대각선 이동
			// 3번 꼭지점 = (y+d1, x-d1)
			// x-d1값이 0보다 크거나 같아야 함 (x - d1 >= 0)
			// 따라서 d1 <= x
			for (int d1 = 1; d1 <= x; d1++) {

				// d2 = 오른쪽 대각선 이동
				// 2번 꼭지점 = (y+d2, x+d2)
				// x+d2값이 n보다 작거나 같아야 함 (x + d2 <= n)
				// 따라서 d2 <= n-x
				for (int d2 = 1; d2 <= n - x; d2++) {
					if (checkBoard(y, x, d1, d2)) {
						// 선거구 경계 위치
						v.push_back(make_pair(y, x));
						v.push_back(make_pair(y + d1, x - d1));
						v.push_back(make_pair(y + d2, x + d2));
						v.push_back(make_pair(y + d1 + d2, x - d1 + d2));
						solve();
					}
				}
			}
		}
	}
	cout << ans;
	return 0;
}
반응형
반응형

문제출처

https://programmers.co.kr/learn/courses/30/lessons/17678

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제풀이

string 형태의 시간을 int형 분으로 변환하여 풀이했다. 변환한 벡터를 오름차순으로 정렬한 뒤 순차적으로 크루들을 탑승시킨다. 이때 마지막 버스인데 타지 못할 경우 마지막 탑승자보다 1분 빨리오는 예외처리가 필요하다. 

2번째 for문에서 탑승할 인원을 체크하고 예외 처리 이후 int형 분을 다시 string형 시간으로 변환하여 return해주면 되는 문제.

핵심은 주어진 문자열을 연산할 때 어떻게 처리하고 정렬을 이용하는 것 같다.

 

소스코드

https://github.com/sw93/algorithm/blob/master/Programmers/kakao2018%20-%20%EC%85%94%ED%8B%80%EB%B2%84%EC%8A%A4.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

#include <string>
#include <vector>
#include <algorithm>
using namespace std;
const int START_BUS_MINUTE = 9 * 60;
const int LAST_BUS_MINUTE = 24 * 60;
int getIntMinute(string time) {
    int ret = ((time[0]-'0')*10 + (time[1]-'0')) * 60;
    ret += (time[3]-'0')*10 + (time[4]-'0');
    return ret;
}
string getStringTime(int time) {
    string ret = to_string((time/600));
    ret += to_string((time/60)%10);
    ret +=  ':';
    ret += to_string((time%60)/10);
    ret += to_string((time%60)%10);
    return ret;
}
string solution(int n, int t, int m, vector<string> timetable) {
    string ret = "";
    vector<int> v;
    for (int i=0; i<timetable.size(); i++) v.push_back(getIntMinute(timetable[i]));
    sort(v.begin(), v.end());
    
    int boardCount = 0;
    int startTime = START_BUS_MINUTE;
    for (int i=0; i<n; i++) {

        // 문제 조건 23:59까지만 가능
    	if (startTime > LAST_BUS_MINUTE) break;
    	int maxBoardCount = m;
        
    	for (int j=boardCount; j<v.size(); j++) {
    		if (maxBoardCount == 0 || v[j] > startTime) break;
            boardCount++;
            maxBoardCount--;
    	}

        // 마지막 버스
    	if (i == n-1) {
            
          // 탑승할 자리가 없는 경우 1분 일찍 나옴
          if (maxBoardCount == 0) startTime = v[boardCount-1] - 1;  
    	}  else startTime += t;
    }
    ret = getStringTime(startTime);
    return ret;
}
반응형
반응형

문제 출처

https://programmers.co.kr/learn/courses/30/lessons/17680

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제풀이

도시이름을 소문자로 모두 바꾼뒤 풀이해야한다. cache 벡터를 사용해서 사용해서 매개변수로 주어진 cacheSize보다 크거나 같을 때 가장 앞에 있는 원소를 삭제해주면 된다. 문제에서 시키는데로 그냥 구현하면 되는 문제.

 

소스코드

https://github.com/sw93/algorithm/blob/master/Programmers/kakao2018%20-%20%EC%BA%90%EC%8B%9C.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int solution(int cacheSize, vector<string> cities) {
    int answer = 0;
    vector<string> cache;
    if (cacheSize == 0) {
        return cities.size() * 5;
    }
    
    for (int i=0; i<cities.size(); i++) {
        transform(cities[i].begin(), cities[i].end(), cities[i].begin(), ::tolower);
        vector<string>::iterator it = find(cache.begin(), cache.end(), cities[i]);
        if (it == cache.end()) {
            if (cache.size() >= cacheSize) cache.erase(cache.begin());
            cache.push_back(cities[i]);
            answer+=5;
        } else {
            cache.erase(it);
            cache.push_back(cities[i]);
            answer++;
        }
    }
    return answer;
}
반응형
반응형

문제 출처

https://programmers.co.kr/learn/courses/30/lessons/17682

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 풀이

if else문을 떡칠해서 풀이했다. 단순히 문제의 조건에 따라 구현해주면 되는 문제라 어렵지 않았다. 단지 이 문제에서 가장 중요했던 점은 2번 조건인 '각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.' 이 문항이다.

dartResult의 1자리씩 끊어서 보다보니까 10이 나온경우 for문의 반복변수를 1개 추가해줘야하기 때문이다.

 

소스 코드

https://github.com/sw93/algorithm/blob/master/Programmers/kakao2018%20-%20%EB%B9%84%EB%B0%80%EC%A7%80%EB%8F%84.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

#include <string>
#include <cmath>
#include <vector>
using namespace std;
int solution(string dartResult) {
    int answer = 0, index = -1;
    vector<int> score;
    for (int i=0; i<dartResult.size(); i++) {
        if (dartResult[i] == 'S') {
        } else if (dartResult[i] == 'D') {
            score[index] = pow(score[index], 2);
        } else if (dartResult[i] == 'T') {
            score[index] = pow(score[index], 3);
        } else if (dartResult[i] == '*') {
            score[index] *= 2;
            if (index > 0) score[index-1] *= 2;
        } else if (dartResult[i] == '#') {
            score[index] *= -1;
        } else {
            index++;
            if (i+1 < dartResult.size() && dartResult[i+1] == '0') {
                score.push_back(10);
                i++;
            } else {
                score.push_back(dartResult[i] - 48);
            }
        }
    }
    for (int i=0; i<score.size(); i++) answer+=score[i];
    return answer;
}

 

반응형
반응형

문제출처

https://programmers.co.kr/learn/courses/30/lessons/17681

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제풀이

2장의 지도를 겹친 값을 얻기 위해 OR 연산을 사용했다. OR연산을 사용하면 문제에서 원하는 전체 지도를 얻을 수 있다. 이후 '#'(벽)과 ' '(공백)을 찾기 위해서는 비트연산을 사용했다. 예를 들어 전체지도의 값이 10진수로 19이라면 2진수로 10011로 나타낼 수 있다. 2진수로 나타낸 값과 1을 오른쪽으로 시프트 한 값(1<<j)의 AND 연산이 1이라면 벽을 추가하고 이외의 경우 공백을 추가하면 된다.

 

비트연산에 대해 이해가 되지 않는다면 아래글을 참조하자.

https://swjeong.tistory.com/114?category=781121

 

[Bitmask] 비트마스크 기초

Bitmask 컴퓨터는 이진번 관련 연산들을 매우 빠르게 진행할 수 있는데, 이러한 특성들을 사용하여 이진수 표현을 자료구조로 사용하는 기법을 비트마스크라고 합니다. 비트마스크는 자료구조라고는 할 수는 없지..

swjeong.tistory.com

 

10011 & 00001 = 1

10011 & 00010 = 1

10011 & 00100 = 0

10011 & 01000 = 0

10011 & 10000 = 1

즉 answer에는 '##  #'의 값이 들어가게 되는데 이는 뒤에서부터 진행한 결과이므로 결과값을 뒤집어 answer 벡터에 추가해주면 된다.

 

 

소스코드

#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<string> solution(int n, vector<int> arr1, vector<int> arr2) {
    vector<string> answer;
    for (int i=0; i<n; i++) {
        int sumValue = (arr1[i] | arr2[i]);
        string ans = "";
        for (int j=0; j<n; j++) {
            if (sumValue & (1<<j)) ans+="#";
            else ans+=" ";
        }
        reverse(ans.begin(), ans.end());
        answer.push_back(ans);   
    }
    return answer;
}

 

반응형
반응형

문제출처

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

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모든 나라는 1×1 크기이기 때문에, 모든 국경선은 정사각형 형태이다. 오늘부터 인구 이동이 시작되는 날이다. 인구 이동은 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다. 국경선을 공유하는 두 나라의 인구 차이가 L명

www.acmicpc.net

 

문제풀이

BFS로 전체탐색하면 되는 문제이다. 

BFS탐색을 통해 연합국가들을 찾으며 총 인구수와 연합국가 수를 구한다. 연합국가가 있는 경우 값을 문제조건대로 갱신해주고 연합국가가 없는경우 인구이동이 일어난 회수를 출력해주면 된다.

이때 연합국가의 좌표를 vector에 저장해 따로 관리해 주면서 갱신해줬다. 삼성기출문제가 점점 응용력이 필요해지는 것 같다. 문제를 주의깊게 읽고 완벽히 이해한뒤 소스코드를 작성하도록 해야겠다.

 

 

소스코드

https://github.com/sw93/algorithm/blob/master/SW_TEST(samsung)/BOJ_16234/BOJ_16234/boj16234.cpp

 

sw93/algorithm

problem solve. Contribute to sw93/algorithm development by creating an account on GitHub.

github.com

#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
bool flag;
int n, l, r, ans;
int dy[] = { 0, -1, 0, 1 };
int dx[] = { 1, 0, -1, 0 };
int map[50][50];
bool visit[50][50];
vector<pair<int, int> > v;
void init() {
	cin >> n >> l >> r;
	for (int y = 0; y < n; y++) {
		for (int x = 0; x < n; x++) {
			cin >> map[y][x];
		}
	}
}
void bfs(int y, int x) {
	int count = 1, sum = map[y][x];
	queue<pair<int, int> > q;
	q.push(make_pair(y, x));
	v.push_back(make_pair(y, x));
	visit[y][x] = 1;
	
	while (!q.empty()) {
		int y = q.front().first;
		int x = q.front().second;
		q.pop();

		for (int i = 0; i < 4; i++) {
			int ny = y + dy[i];
			int nx = x + dx[i];
			if (ny < 0 || nx < 0 || ny >= n || nx >= n || visit[ny][nx]) continue;

			int diff = abs(map[y][x] - map[ny][nx]);
			if (diff >= l && diff <= r) {
				visit[ny][nx] = 1;
				sum += map[ny][nx];
				count++;
				q.push(make_pair(ny, nx));
				v.push_back(make_pair(ny, nx));
			}
		}
	}

	if (v.size() > 1) {
		flag = 1;
		int updateValue = sum / count;
		for (int i = 0; i < v.size(); i++) map[v[i].first][v[i].second] = updateValue;	
	}
	v.clear();
}
int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);
	init();
	while (true) {
		memset(visit, 0, sizeof(visit));
		flag = 0;
		for (int y = 0; y < n; y++) {
			for (int x = 0; x < n; x++) {
				if (visit[y][x]) continue;
				bfs(y, x);
			}
		}
		if (flag) ans++;
		else break;
	}
	cout << ans << "\n";
	return 0;
}
반응형

+ Recent posts