본문 바로가기

스터디

알고리즘 스터디 - 큐

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

 

14226번: 이모티콘

영선이는 매우 기쁘기 때문에, 효빈이에게 스마일 이모티콘을 S개 보내려고 한다. 영선이는 이미 화면에 이모티콘 1개를 입력했다. 이제, 다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만

www.acmicpc.net

 

솔루션


처음에 접근법이 잘 안떠올라 고생했다.

 

기존의 BFS와 유사한데, 복사라는 기능이 추가되어 까다로웠다.

 

나는 2차원 배열로 잡고, 우선순위 큐를 이용해 해결하였다.

 

우선순위 큐는

{텍스트 길이, 복사된 문자 길이, 총 시간} 으로 잡고 정렬 순서는

시간이 가장 작은 것이 top에 위치 하도록 하였다.

 

그리고 시작은 {1,0,0}으로 시작하여서 다음 3가지 경우로 나눴다.

 

1. 현재 이모티콘을 복사하여 다시 붙여넣는경우

 이때는 시간이 2초 소모되며, 텍스트 길이는 2배, 복사된 문자 길이는 텍스트 길이, 시간은 +2 가 된다.

 

2. 복사된 이모티콘을 또 붙여넣는 경우

 이때는 시간 1초 소모되며, {텍스트 길이 + 복사된 문자 길이, 복사된 문자 길이, 시간+1} 이 되며

 

3. 문자 하나를 지우는 겨웅

시간이 1초 소모 되며 {텍스트 길이 - 1, 복사된 문자 길이, 시간+1} 이 된다.

 

그리고 우선순위 큐를 이용하였으므로 S에 도달하게 되면 가장 작은 최소값이므로 바로 출력하고 종료한다.

 

 

코드


#define INF 987654321
#include <iostream>
#include <queue>
using namespace std;

struct pa {
	int num, copy, cnt;
	bool operator<(const struct pa& t)const {
		if (cnt == t.cnt) {
			return num > t.num;
		}
		return cnt > t.cnt;
	}
};

int arr[2002][2002];
priority_queue<pa> Q;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);

	int N;
	cin >> N;

	for (int i = 1; i <= 2000; i++) {
		for (int j = 1; j <= 2000; j++) arr[i][j] = INF;
	}

	Q.push({ 1,0,0 });
	int ans = INF;

	while (!Q.empty()) {
		int cur = Q.top().num;
		int copy = Q.top().copy;
		int cnt = Q.top().cnt;
		Q.pop();

		if (cur> N+200) continue;
		if (cnt > arr[cur][copy]) continue;
		if (cur == N) {
			cout << cnt << '\n';
			return 0;
		}

		if (cur + cur <= 1200 && arr[cur+cur][cur]  > cnt+2) {
			Q.push({ cur + cur,cur,cnt + 2 });
			arr[cur + cur][cur] = cnt + 2;
		}
		if (cur + copy <= 1200 && arr[cur + copy][copy] > cnt + 1) {
			Q.push({ cur + copy,copy,cnt+1});
			arr[cur + copy][copy] = cnt + 1;
		}
		if (cur - 1 > 1 && arr[cur - 1][copy] > cnt + 1) {
			Q.push({ cur - 1,copy,cnt +1});
			arr[cur - 1][copy] = cnt + 1;
		}

	}
}

 

 


 

 

 

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

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net

 

솔루션


처음에 밑/오른쪽으로만 갈 수 있다고 생각하여서 문제를 접근하였다가 정답이 나오지 않아서 문제를 다시 읽었다.

 

 

상하좌우 다 움직일 수 있도록 하였고, 또한 벽을 부술 수 있는 것은 1개 이기 때문에 3차원 배열을 만들어서 해결하였다.

 

[2][N][M] 사이즈로 배열을 잡아서 해결하였고, 벽을 부수지 않았다면 [0][x][y]에 초기화 하였고

벽을 부수고 온 지점이라면 [1][x][y]로 처리 하여서 N,M지점에 도착했을 때 총 움직인 회수를 출력하였다.

 

 

코드


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

bool visit[2][1002][1002];
struct pa {
	int x, y, c;
	bool b;
};
string str[1002];
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);

	int N, M;
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		cin >> str[i];
	}
	
	queue<pa> Q;
	Q.push({ 0,0,1,false });

	int ans = -1;
	while (!Q.empty()) {
		pa cur = Q.front();
		Q.pop();

		if (cur.x +1== N && cur.y+1 == M) {
			if (ans == -1) {
				ans = cur.c;
			}
			else {
				ans = min(cur.c, ans);
			}
		}
		for (int i = 0; i < 4; i++) {
			int tx = dx[i] + cur.x;
			int ty = dy[i] + cur.y;
			
			if (tx >= 0 && tx < N && ty >= 0 && ty < M) {
				if (str[tx][ty] == '1' && !cur.b&& !visit[1][tx][ty]) {
					Q.push({ tx,ty,cur.c + 1, true });
					visit[1][tx][ty] = true;
				}
				if(str[tx][ty] == '0'&& !visit[cur.b][tx][ty]) {
					Q.push({ tx,ty,cur.c + 1,cur.b });
					visit[cur.b][tx][ty] = true;
				}
			}
		}
	}

	cout << ans << '\n';
}

'스터디' 카테고리의 다른 글

우선순위 큐  (0) 2023.07.04
Deque 활용 문제 풀이  (0) 2023.06.01
[스터디] 연결리스트(Linked List)  (2) 2023.05.18
1-1 중복이 없는가?  (0) 2023.05.11