const fs = require('fs');
// const input = fs.readFileSync('./testcase.txt').toString().trim();
const input = fs.readFileSync('/dev/stdin').toString().trim();

const inputs = input.split('\n');
const N = inputs[0];

function initMethodInArrayPrototype() {
    if (
        Array.prototype.at === undefined ||
        typeof Array.prototype.at !== 'function'
    ) {
        Array.prototype.at = (index) => {
            if (index >= 0) {
                if (index < this.length) return this[index];
                else return undefined;
            }
            else {
                const ridx = index * -1;
                if (ridx > this.length) return undefined;
                return this[this.length - ridx];
            }
        }
    }
}

class Stack {
    constructor() {
        this.stack = [];
    }
    push(x) {
        this.stack.push(x);
    }
    pop() {
        if (this.stack.length === 0) {
            return -1;
        } else {
            return this.stack.pop();
        }
    }
    size() {
        return this.stack.length;
    }
    empty() {
        return this.stack.length ? 0 : 1;
    }
    top() {
        if (this.stack.length) {
            return this.stack.at(-1);
        } else {
            return -1;
        }
    }
}

initMethodInArrayPrototype();
const stack = new Stack();
let answer = '';

for (let i = 1; i <= N; i++) {
    const [req, num] = [...inputs[i].split(' ')];
    if (req === 'push') {
        stack.push(+num);
    }
    if (req === 'pop') {
        answer += stack.pop() + '\n';
    }
    if (req === 'size') {
        answer += stack.size() + '\n';
    }
    if (req === 'top') {
        answer += stack.top() + '\n';
    }
    if (req === 'empty') {
        answer += stack.empty() + '\n';
    }
}

console.log(answer);

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

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

 

 

'algorithm > BOJ' 카테고리의 다른 글

BOJ 1486번 등산  (1) 2021.04.17
BOJ 2273번 줄 서기  (0) 2021.04.17
BOJ 3584번 가장 가까운 공통 조상  (0) 2021.03.31
BOJ 1103번 게임  (0) 2021.03.16
BOJ 2194번 유닛 이동시키기 C++  (0) 2020.07.05

BOJ : www.acmicpc.net/problem/1486

 

1486번: 등산

첫째 줄에 산의 세로크기 N과 가로크기 M 그리고, T와 D가 주어진다. N과 M은 25보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 지도가 주어진다. T는 52보다 작거나 같은 자연수이고, D는 1,000

www.acmicpc.net

문제

세준이가 가려고하는 산의 지도가 입력으로 주어진다. 산의 지도를 M이라고 했을 때, M[i][j]는 (i,j)의 높이가 M[i][j]라는 것을 의미한다. 그 값이 'A'-'Z'일 때는 0-25를 뜻하는 것이고, 'a'-'z'일 때는, 26-51을 뜻한다.

세준이의 호텔은 (0,0)에 있다. 그리고, 세준이는 지금 위치에서 바로 인접한 정수 좌표 중 높이의 차이가 T보다 크지 않은 곳으로만 다닐 수 있다.

만약 세준이가 현재 위치에서 높이가 낮은 곳이나 같은 곳으로 이동한다면 시간은 1초가 걸린다. 하지만 높은 곳으로 이동한다면 두 위치의 높이의 차이의 제곱만큼 시간이 걸린다. 예를 들어 높이가 5에서 높이가 9인 곳으로 간다면, 시간은 (5-9)2=16초가 걸린다. 하지만, 높이가 9인 곳에서 5인 곳으로 간다면 시간은 1초가 걸린다.

산의 지도와, T, 그리고 어두워지는 시간 D가 주어졌을 때, 세준이가 D보다 크지 않은 시간 동안 올라갈 수 있는 최대 높이를 구하는 프로그램을 작성하시오.(세준이는 호텔에서 출발해서 호텔로 돌아와야 한다.)

 

입력

첫째 줄에 산의 세로크기 N과 가로크기 M 그리고, T와 D가 주어진다. N과 M은 25보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 지도가 주어진다. T는 52보다 작거나 같은 자연수이고, D는 1,000,000보다 작거나 같은 자연수이다.

 

출력

첫째 줄에 세준이가 갈 수 있는 가장 높은 곳의 높이를 출력한다.

 

풀이

문제에 접근해보면 (0.0)에서 출발해서 어느 지점 (y,x) 을 지나 다시 제자리(0.0) 으로 돌아오는 문제다

그 과정에서 y,x -> yy,xx 로 이동할 때

y,x 가 yy,xx 보다 같거나 크면 시간이 +1

y,x 가 yy,xx 보다 작으면 그 차이만큼 제곱한 시간을 더해주게 된다

결국 (0,0)에서 (y,x)로 이동하는데 걸리는 시간D1 과 (y,x)에서 (0,0)으로 이동하는데 걸리는 시간 D2

D1 + D2가 D보다 작은 모든 경우 중에서 가장 큰 좌표의 높이를 구하는 문제이다

 

결론 => 

(0,0)으로부터 모든 좌표로의 최소시간

(y,x)으로부터 모든 좌표로의 최소시간

다익스트라를 사용하여 문제를 해결

 

minHeap을 사용해야하는데 계속 maxHeap을 사용하는 실수를 하네..?

 

더보기
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <cmath>
using namespace std;

struct pii{
	int time, y, x;
};

struct compare {
	bool operator()(pii& a, pii& b) {
		return a.time > b.time;
	}
};

#define INF 987654321
int my[4] = { -1,1,0,0 };
int mx[4] = { 0,0,1,-1 };
string arra[30];
int arr[30][30];
int dp[30][30][30][30];
int N, M, T, D;

void getDijkstra(int sy, int sx) {

	priority_queue<pii, vector<pii>, compare> pq;
	pq.push({ 0, sy, sx });
	dp[sy][sx][sy][sx] = 0;
	while (!pq.empty()) {
		int y = pq.top().y;
		int x = pq.top().x;
		int time = pq.top().time;
		pq.pop();

		if (dp[sy][sx][y][x] < time) continue;

		for (int i = 0; i < 4; i++) {
			int yy = y + my[i];
			int xx = x + mx[i];
			if (yy < 0 || xx < 0 || yy >= N || xx >= M) continue;

			if (abs(arr[y][x] - arr[yy][xx]) > T) continue;
			
			int nextTime;
			if (arr[y][x] >= arr[yy][xx]) {
				nextTime = time + 1;
			}
			else {
				nextTime = pow(abs(arr[y][x] - arr[yy][xx]), 2) + time;
			}

			if (nextTime < dp[sy][sx][yy][xx]) {
				dp[sy][sx][yy][xx] = nextTime;
				pq.push({ nextTime, yy, xx });
			}
		}
	}
}

int dijkstra() {

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			for (int a = 0; a < N; a++) {
				for (int b = 0; b < M; b++) {
					dp[i][j][a][b] = INF;
				}
			}
		}
	}

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			getDijkstra(i, j);
		}
	}

	int answer = 0;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (dp[0][0][i][j] == INF || dp[i][j][0][0] == INF) continue;
			int calTime = dp[0][0][i][j] + dp[i][j][0][0];
			if (calTime <= D) {
				answer = max(answer, arr[i][j]);
			}
		}
	}

	return answer;
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);

	cin >> N >> M >> T >> D;
	for (int i = 0; i < N; i++) {
		cin >> arra[i];
		for (int j = 0; j < M; j++) {
			if (arra[i][j] >= 'A' && arra[i][j] <= 'Z') arr[i][j] = arra[i][j] - 'A';
			else arr[i][j] = arra[i][j] - 'a' + 26;
		}
	}

	cout << dijkstra();
}

 

'algorithm > BOJ' 카테고리의 다른 글

[JS & Stack] 10828번: 스택  (0) 2023.07.19
BOJ 2273번 줄 서기  (0) 2021.04.17
BOJ 3584번 가장 가까운 공통 조상  (0) 2021.03.31
BOJ 1103번 게임  (0) 2021.03.16
BOJ 2194번 유닛 이동시키기 C++  (0) 2020.07.05

BOJ : www.acmicpc.net/problem/2273

 

2273번: 줄 서기

첫째 줄에 N(1≤N≤256), M(1≤M≤100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의미이다.

www.acmicpc.net

 

문제

N명의 학생들이 키 순서대로 줄을 서려고 한다. 각 학생의 키를 직접 재서 정렬하면 간단하겠지만, 마땅한 방법이 없어서 두 학생의 키를 비교하는 방법을 사용하기로 하였다. 그나마도 모든 학생들을 다 비교해 본 것이 아니고, 일부 학생들의 키만을 비교해 보았다.

일부 학생들의 키를 비교한 결과가 주어졌을 때, 각 학생이 설 수 있는 위치의 범위를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 N(1≤N≤256), M(1≤M≤100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의미이다. 같은 학생들을 여러 번 비교했을 수도 있다.

 

출력

N개의 줄에 각 학생이 설 수 있는 위치의 범위를 출력한다. 불가능한 경우에는 첫째 줄에 -1을 출력한다.

 

 

풀이

요즘 문제 풀기가 바빠 포스팅을 잘 안했는데, 이번 문제는 내가 코드를 꼼꼼히 작성하지 않는다는 것과 아무 생각없이 문제를 접근한다는거에 대한 반성의 의미로 포스팅하게 되었다.

이미 비교되어 있는 정점에서 서로 다른 정점과의 비교값을 얻기 위한 이와 같은 문제는 플로이드 와샬로 접근해야한다.

 

처음에는 플로이드와샬로 접근해놓고 모든 조합을 구하기 위해 DFS를 사용했는데,, 왜그런거야..

이 문제의 해결법은 나보다 키가 작은사람, 키가 큰사람의 인원수만 구하면 되는건데........

현재 학생과 다른 학생들 간의 대소관계를 비교하는 플로이드 과정이 끝나면

현재 학생이 가질 수 있는 범위는 다음과 같아진다

left : 1, right : N 일때

나보다 큰 학생이 있는 경우 left+1

나보다 작은 학생이 있는 경우 right-1

이렇게 간단하게 범위를 계산할 수 있게 된다

 

더보기
#include <iostream>
using namespace std;
int arr[257][257], N, M, s, e, l, r;
int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> N >> M;
	
	for (int i = 0; i < M; i++) {
		cin >> s >> e;
		if (arr[s][e] == -1 || arr[e][s] == 1) {
			cout << "-1";
			return 0;
		}
		arr[s][e] = 1;
		arr[e][s] = -1;
	}
	for (int k = 1; k <= N; k++) {
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if (i == j) continue;
				if (arr[i][j] != 0) {
					if ((arr[i][j] == arr[j][i]) || (arr[i][k] == 1 && arr[k][j] == 1 && (arr[i][j] == -1 || arr[j][i] == 1)) || (arr[i][k] == -1 && arr[k][j] == -1 && (arr[i][j] == 1 || arr[j][i] == -1))) {
						cout << "-1";
						return 0;
					}
				}
				if (arr[i][j] == 0) {
					if (arr[i][k] == arr[k][j]) {
						arr[i][j] = arr[i][k];
						arr[j][i] = -arr[i][j];
					}
				}
			}
		}
	}
	for (int i = 1; i <= N; i++) {
		l = 1, r = N;
		for (int j = 1; j <= N; j++) {
			if (arr[i][j] == 1) r--;
			else if (arr[i][j] == -1) l++;
		}
		cout << l << " " << r << "\n";
	}
}

 

'algorithm > BOJ' 카테고리의 다른 글

[JS & Stack] 10828번: 스택  (0) 2023.07.19
BOJ 1486번 등산  (1) 2021.04.17
BOJ 3584번 가장 가까운 공통 조상  (0) 2021.03.31
BOJ 1103번 게임  (0) 2021.03.16
BOJ 2194번 유닛 이동시키기 C++  (0) 2020.07.05

BOJ : www.acmicpc.net/problem/3584

 

3584번: 가장 가까운 공통 조상

루트가 있는 트리(rooted tree)가 주어지고, 그 트리 상의 두 정점이 주어질 때 그들의 가장 가까운 공통 조상(Nearest Common Anscestor)은 다음과 같이 정의됩니다. 두 노드의 가장 가까운 공통 조상은, 두

www.acmicpc.net

 

루트가 있는 트리(rooted tree)가 주어지고, 그 트리 상의 두 정점이 주어질 때 그들의 가장 가까운 공통 조상(Nearest Common Anscestor)은 다음과 같이 정의됩니다.

  • 두 노드의 가장 가까운 공통 조상은, 두 노드를 모두 자손으로 가지면서 깊이가 가장 깊은(즉 두 노드에 가장 가까운) 노드를 말합니다.

예를 들어  15와 11를 모두 자손으로 갖는 노드는 4와 8이 있지만, 그 중 깊이가 가장 깊은(15와 11에 가장 가까운) 노드는 4 이므로 가장 가까운 공통 조상은 4가 됩니다.

루트가 있는 트리가 주어지고, 두 노드가 주어질 때 그 두 노드의 가장 가까운 공통 조상을 찾는 프로그램을 작성하세요

 

풀이

최근 있었던 코딩테스트에서 LCA를 기반으로 하는 문제가 출제되었는데,

지식이 없어서 풀지 못했었다.

LCA 알고리즘을 공부한 후에 3584번 문제를 풀게 되었는데,

당연히 LCA 로 풀 수 있지만, 어떤 알고리즘이든 기본 베이스가 중요하다고 생각하며, 특히 이 문제는 쿼리의 범위가 작기 때문에 이번에는 LCA 알고리즘이 아닌, 일반 dfs로 문제를 풀어보았다.

 

접근은 LCA 알고리즘과 비슷하게 

1. depth를 갖는 정보를 만들어 준 후에

2. LCA를 알고자하는 두 정점을 입력받으면 두 정점의 depth를 먼저 맞춰주고

3. depth가 동일할 때 두 정점이 다르다면, 다시 parent를 찾아 올라가면서 최소공통조상을 찾아주었다.

 

 

// LCA 알고리즘을 사용하지 않은 풀이

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

int depth[10001];
int parent[10001];
vector<int> v[10001];

void calDepth(int now, int myparent) {

	depth[now] = depth[myparent] + 1;

	for (int i = 0; i < v[now].size(); i++) {
		int next = v[now][i];
		if (next != myparent) {
			calDepth(next, now);
		}
	}

}

int main() {
	int T; cin >> T;
	while (T--) {
		int N; cin >> N;
		for (int i = 1; i <= N; i++) v[i].clear();
		memset(parent, 0, sizeof(parent));

		for (int i = 1; i < N; i++) {
			int f, s;
			cin >> f >> s;
			v[f].push_back(s);
			parent[s] = f;
		}

		// 루트정점이 뭔지 모르기 때문에, 1~N 중 부모가 없는 정점을 찾는다
		int root;
		for (int i = 1; i <= N; i++) {
			if (parent[i] == 0) {
				root = i;
				break;
			}
		}

		// root 정점부터 depth를 계산한다
		depth[0] = -1;
		calDepth(root, 0);

		// depth 계산이 끝났으면 LCA를 찾는다
		int f, s;
		cin >> f >> s;

		// 정점 f, s의 depth가 다르다면
		if (depth[f] != depth[s]) {
			
			// 정점 f를 상향한다고 가정
			if (depth[f] < depth[s])
				swap(f, s);

			// depth를 맞춘다
			while (depth[f] > depth[s]) {
				f = parent[f];
			}
		}

		// f와 s가 서로 같은 정점이면
		if (f == s) {
			cout << f << "\n";
		}
		else {
			while (parent[f] != parent[s]) {
				f = parent[f];
				s = parent[s];
			}
			cout << parent[f] << "\n";
		}
	}
}

'algorithm > BOJ' 카테고리의 다른 글

BOJ 1486번 등산  (1) 2021.04.17
BOJ 2273번 줄 서기  (0) 2021.04.17
BOJ 1103번 게임  (0) 2021.03.16
BOJ 2194번 유닛 이동시키기 C++  (0) 2020.07.05
BOJ 14750번 Jerry and Tom  (0) 2020.04.28

+ Recent posts