반응형

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

 

1854번: K번째 최단경로 찾기

첫째 줄에 n, m, k가 주어진다. (1 ≤ n ≤ 1000, 0 ≤ m ≤ 2000000, 1 ≤ k ≤ 100) n과 m은 각각 김 조교가 여행을 고려하고 있는 도시들의 개수와, 도시 간에 존재하는 도로의 수이다. 이어지는 m개의 줄에

www.acmicpc.net

1.문제설명

백준 1854번

1번 노드에서 출발하여 다른 모든 노드까지의 K번째 최단 거리를 찾는 문제이다.

 

일반적으로

한 노드에서 다른 모든 노드까지의 최단 거리를 구할 때 다익스트라 알고리즘을 이용한다.

 

이 문제도 다익스트라 알고리즘을 응용하면 K번째 최단거리를 구할 수 있다.

 

 


 

2.접근방법[알고리즘]

 

이 문제에서 가장 헷갈리는 점은 

기존 최단거리를 구하는 다익스트라 알고리즘과 다르게

방문한 노드를 재방문해도 된다는 점이다.

 

방문한 노드를 재방문해도 되도록 코드를 구성하면

계속 무한루프에 빠지지 않을까?

 

이를 해결하기 위해 

방문 여부 대신 다른 조건을 추가해주어야 한다.

 

 

백준 1854번

 

그림에 잘 보면 2->3->5->2가 계속 무한으로 순환할 수 있다.

 

노드를 방문하는 우선순위큐와 다르게

 

특정 노드까지 거리를 저장하는 우선순위큐 배열을 따로 두어서

 

K번째 최단 거리까지 구했다면 더 이상 순환하지 않도록 코드를 구현해야 한다.

 

 

 

 

 

 

 

 

 


 

3.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;

int n, m, k;
struct Edge {
	int x;
	long long val;
	bool operator<(const Edge& b) const {
		return val > b.val;
	}
};

vector<pair<int, int> > graph[1001];
priority_queue<int> Node[1001];
priority_queue<Edge> Q;

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

	cin >> n >> m >> k;

	for (int i = 0; i < m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		graph[a].push_back({ b,c });
	}

	Node[1].push(0);
	Q.push({ 1,0 });

	while (!Q.empty()) {
		int x = Q.top().x;
		int val = Q.top().val;
		Q.pop();

		for (int i = 0; i < graph[x].size(); i++) {
			int nx = graph[x][i].first;
			int nd = graph[x][i].second + val;

			if (Node[nx].size() < k) {
				Node[nx].push(nd);
				Q.push({ nx,nd });
			}
			else {
				if (Node[nx].top() > nd) {
					Node[nx].pop();
					Node[nx].push(nd);
					Q.push({ nx,nd });
				}
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		if (Node[i].size() < k) {
			cout << -1 << '\n';
		}
		else {
			cout << Node[i].top() << '\n';
		}
	}


	return 0;
}

백준 1854번

반응형
반응형

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

 

1507번: 궁금한 민호

강호는 N개의 도시로 이루어진 나라에 살고 있다. 각 도시는 M개의 도로로 연결되어 있으며, 각 도로를 지날 때 필요한 시간이 존재한다. 도로는 잘 연결되어 있기 때문에, 도시 A에서 B로 이동할

www.acmicpc.net

1.문제설명

INPUT

5
0 6 15 2 6
6 0 9 8 12
15 9 0 16 18
2 8 16 0 4
6 12 18 4 0

OUTPUT

55

문제에서 N개의 노드가 있을 때

노드에서 노드로 가는 모든 최단 거리를 INPUT으로 준다.

 

 

주어진 노드간 최단 거리를 유지하면서 간선의 개수를 최소로 할 때 

간선의 거리의 합을 구해야 한다.

 

 


2.접근방법[알고리즘]

 

주어진 인풋을 dist배열에 넣고

 

플로이드 워셜을 한번 실행했을 때

 

dist[i][k] + dist[k][j]) == dist[i][j]

이런 상황이 있으면 간선을 최소로 하기위해

dist[i][j] 의 간선을 사용하지 않고

dist[i][k] 와 dist[k][j]의 간선만 사용하면 된다.

 

 

맨 처음엔 문제에서 주어진 인풋의 간선을 모두 사용하는 걸 전제로 하고

위와 같은 간선이 있으면 i - j 를 이어주는 간선을 없애주면

최소 간선을 구해낼 수 있다.

 

for (int k = 0; k < n; k++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i == j || j == k || i == k) continue;
				if ((dist[i][k] + dist[k][j]) == dist[i][j]) {
					arr[i][j] = INF;
				}
				else if (dist[i][k] + dist[k][j] < dist[i][j]) {
					cout << -1 << '\n';
					return 0;
				}
			}
		}
	}

 

 

 

 

 


 

3. 문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;


const int INF = 0x3f3f3f3f;

int n, arr[21][21];

int dist[21][21];
bool ch[21][21];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	memset(dist, 0x3f, sizeof(dist));

	cin >> n;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> arr[i][j];
			dist[i][j] = min(dist[i][j], arr[i][j]);
		}
	}

	for (int k = 0; k < n; k++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i == j || j == k || i == k) continue;
				if ((dist[i][k] + dist[k][j]) == dist[i][j]) {
					arr[i][j] = INF;
				}
				else if (dist[i][k] + dist[k][j] < dist[i][j]) {
					cout << -1 << '\n';
					return 0;
				}
			}
		}
	}

	int sum = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (arr[i][j] < INF) sum += arr[i][j];
		}
	}

	cout << sum / 2 << '\n';



	return 0;
}
반응형
반응형

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

 

1956번: 운동

첫째 줄에 V와 E가 빈칸을 사이에 두고 주어진다. (2 ≤ V ≤ 400, 0 ≤ E ≤ V(V-1)) 다음 E개의 줄에는 각각 세 개의 정수 a, b, c가 주어진다. a번 마을에서 b번 마을로 가는 거리가 c인 도로가 있다는 의

www.acmicpc.net

 

플로이드 와샬 알고리즘을 이용해 풀고

 

거리의 최대치와 INT StackOverflow를 유의해서 풀어야한다.

 

#include <bits/stdc++.h>
using namespace std;

const int INF = 2e9;
int n,m, dist[401][401];

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

	fill(&dist[0][0], &dist[400][401], INF);

	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		dist[a][b] = c;
	}

	for (int k = 1; k <= n; k++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (dist[i][k] >= INF || dist[k][j] >= INF) continue;
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
			}
		}
	}

	int ans = INT_MAX;
	for (int i = 1; i <= n; i++) {
		ans = min(dist[i][i], ans);
	}

	if (ans == INF) {
		cout << -1 << '\n';
	}
	else {
		cout << ans << '\n';
	}
	return 0;
}

백준 1956

반응형
반응형

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

 

2458번: 키 순서

1번부터 N번까지 번호가 붙여져 있는 학생들에 대하여 두 학생끼리 키를 비교한 결과의 일부가 주어져 있다. 단, N명의 학생들의 키는 모두 다르다고 가정한다. 예를 들어, 6명의 학생들에 대하여

www.acmicpc.net

1.문제설명

서로 키를 비교한 결과를 입력으로 주었을 때

 

키의 순서를 알 수있는 노드가 몇 개인지 구하는 문제이다.

 

2.접근방법

해당 노드의 키 순서를 알려면

 

해당 노드를 제외한 모든 노드와 비교가 되어야 한다.

 

플로이드 와샬 알고리즘으로 모든 노드간 거리를 구했을 때

 

만약 거리[a][b] 와 거리[b][a]가 모두 비교가 되지 않은 채 INF 값이 있다면

 

 a와 b는 순서를 알 수 없다.

 

 

 

 

3.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;



int n, m, dist[501][501];

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

	memset(dist, 0x3f, sizeof(dist));

	cin >> n >> m;

	for (int i = 1; i <= n; i++) {
		dist[i][i] = 0;
	}

	for (int i = 0; i < m; i++) {
		int a, b;
		cin >> a >> b;
		dist[a][b] = 1;
	}


	for (int k = 1; k <= n; k++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
			}
		}
	}

	int ans = 0;
	for (int i = 1; i <= n; i++) {

		bool canKnow = true;
		for (int j = 1; j <= n; j++) {
			if (dist[i][j] > 10000) {
				if (dist[j][i] > 10000) {
					canKnow = false;
				}

			}
		}

		if (canKnow) ans++;

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


	return 0;
}

백준 2458번

 

반응형
반응형

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

 

2610번: 회의준비

첫째 중에 회의에 참석하는 사람의 수 N이 주어진다. 참석자들은 1부터 N까지의 자연수로 표현되며 회의에 참석하는 인원은 100 이하이다. 둘째 줄에는 서로 알고 있는 관계의 수 M이 주어진다. 이

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;


int n,k;
int dist[101][101];
bool grouped[101];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	memset(dist, 0x3f, sizeof(dist));

	cin >> n >> k;

	for (int i = 0; i < k; i++) {
		int a, b;
		cin >> a >> b;
		dist[a][b] = 1;
		dist[b][a] = 1;
	}

	for (int i = 1; i <= n; i++) {
		dist[i][i] = 0;
	}

	for (int k = 1; k <= n; k++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
			}
		}
	}
	
	int cnt = 0;

	vector<int> king;

	for (int i = 1; i <= n; i++) {
		vector<int> g;
		for (int j = 1; j <= n; j++) {
			if (dist[i][j] < 200 && grouped[j] == false) {
				grouped[j] = true;
				g.push_back(j);
			}
		}
		
		if (g.size() > 0) {
			cnt++;

			int minn = INT_MAX;
			int midx = -1;

			for (int j = 0; j < g.size(); j++) {

				int maxx = 0;
				for (int k = 0; k < g.size(); k++) {
					maxx = max(maxx, dist[g[j]][g[k]]);
				}
				if (maxx < minn) {
					minn = maxx;
					midx = g[j];
				}
			}
			king.push_back(midx);
		}
	}

	sort(king.begin(), king.end());

	cout << cnt << '\n';
	for (int i = 0; i < king.size(); i++) {
		cout << king[i] << '\n';
	}

	return 0;
}

백준 2610번

반응형
반응형

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

 

8983번: 사냥꾼

입력의 첫 줄에는 사대의 수 M (1 ≤ M ≤ 100,000), 동물의 수 N (1 ≤ N ≤ 100,000), 사정거리 L (1 ≤ L ≤ 1,000,000,000)이 빈칸을 사이에 두고 주어진다. 두 번째 줄에는 사대의 위치를 나타내는 M개의 x-좌

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;

vector<int> gun;


bool distance(int x, int y, int L) {

	bool ans = false;
	if (y > L) return false;

	int s = 0;
	int e = gun.size() - 1;

	while (s <= e) {

		int mid = (s + e) / 2;

		if (abs(gun[mid] - x) + y <=L) {
			ans = true;
			break;
		}
		else if (gun[mid] > x) {
			e = mid - 1;
		}
		else {
			s = mid + 1;
		}
	}


	return ans;
}


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

	int m, n, l;
	cin >> m >> n >> l;
	

	for (int i = 0; i < m; i++) {
		int tmp;
		cin >> tmp;
		gun.push_back(tmp);
	}

	sort(gun.begin(), gun.end());

	int cnt = 0;
	for (int i = 0; i < n; i++) {
		int x, y;
		cin >> x >> y;
		if (distance(x, y ,l)) cnt++;
	}

	cout << cnt << '\n';


	

	return 0;
}

백준 8983번

반응형
반응형

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

 

6087번: 레이저 통신

크기가 1×1인 정사각형으로 나누어진 W×H 크기의 지도가 있다. 지도의 각 칸은 빈 칸이거나 벽이며, 두 칸은 'C'로 표시되어 있는 칸이다. 'C'로 표시되어 있는 두 칸을 레이저로 통신하기 위해서

www.acmicpc.net

 

 

 

#include <bits/stdc++.h>
using namespace std;

int w, h;
int stx, sty, enx, eny;
int arr[101][101];
int dis[101][101];

int dx[4] = { -1, 0,1,0 };
int dy[4] = { 0, 1,0,-1 };

struct Node {
	int x, y, dist, direction;

	bool operator<(const Node& b) const {
		return dist > b.dist;
	}
};



int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	memset(dis, 0x3f, sizeof(dis));

	cin >> w >> h;
	bool st = false;

	for (int i = 0; i < h; i++) {
		string s;
		cin >> s;
		for (int j = 0; j < w; j++) {
			if (s[j] == '*') {
				arr[i][j] = -1;
			}
			else if (s[j] == 'C' && st == false) {
				stx = i;
				sty = j;
				st = true;
			}
			else if (s[j] == 'C' && st == true) {
				enx = i;
				eny = j;
			}
		}
	}


	priority_queue<Node> Q;

	dis[stx][sty] = 0;

	for (int i = 0; i < 4; i++) {
		int nx = stx + dx[i];
		int ny = sty + dy[i];

		if (nx < 0 || nx >= h || ny < 0 || ny >= w || arr[nx][ny]==-1 ) continue;

		Q.push({ nx,ny,0,i });
	}


	while (!Q.empty()) {
		int x = Q.top().x;
		int y = Q.top().y;
		int dist = Q.top().dist;
		int direction = Q.top().direction;
		Q.pop();


		if (dis[x][y] < dist) continue;
		dis[x][y] = dist;

		if (x == enx && y == eny) {
			cout << dist << '\n';
			return 0;
		}

		for (int i = 0; i < 4; i++) {
			if (abs(i - direction) == 2) continue;

			int nx = x + dx[i];
			int ny = y + dy[i];
			int nd = dist;
			if (i != direction) {
				nd++;
			}
			if (nx < 0 || nx >= h || ny < 0 || ny >= w || arr[nx][ny] == -1) continue;
			if (dis[nx][ny] < nd) continue;
			Q.push({ nx,ny,nd,i });
		}
	}



	//for (int i = 0; i < h; i++) {
	//	for (int j = 0; j < w; j++) {
	//		if (dis[i][j] > 10) cout << '*';
	//		else cout << dis[i][j];
	//	}
	//	cout << '\n';
	//}


	return 0;
}

백준 6087번

반응형
반응형

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

 

2108번: 통계학

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;

struct Count {
	int x, cnt;

	bool operator<(const Count& b) const {
		if (cnt == b.cnt) {
			return x < b.x;
		}
		return cnt > b.cnt;
	}
};

int arr[9000];

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

	int n;
	vector<int> v;

	cin >> n;
	int sum = 0;
	for (int i = 0; i < n; i++) {
		int tmp;
		cin >> tmp;
		sum += tmp;

		arr[tmp + 4000]++;
		v.push_back(tmp);
	}

	sort(v.begin(), v.end());

	vector<Count> freq;

	for (int i = 0; i < 9000; i++) {
		if (arr[i] > 0) {
			freq.push_back({ i,arr[i] });
		}
	}

	sort(freq.begin(), freq.end());

	int freq_ans = freq[0].x - 4000;
	if (freq.size() >= 2 && freq[0].cnt == freq[1].cnt) {
		freq_ans = freq[1].x - 4000;
	}
	

	double mean = sum / (double)n;

	int mm;
	if (mean >= 0) {
		mm = int(mean + 0.5);
	}
	else {
		mm = int(mean - 0.5);
	}

	cout << mm << '\n';
	cout << v[n / 2] << '\n';

	cout << freq_ans << '\n';

	cout << v[v.size() - 1] - v[0] << '\n';
	
	return 0;
}

백준 2108번

반응형

+ Recent posts