반응형

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

 

9370번: 미확인 도착지

(취익)B100 요원, 요란한 옷차림을 한 서커스 예술가 한 쌍이 한 도시의 거리들을 이동하고 있다. 너의 임무는 그들이 어디로 가고 있는지 알아내는 것이다. 우리가 알아낸 것은 그들이 s지점에서

www.acmicpc.net

 

1.문제설명

백준 9370번

문제가 꽤 복잡하다.

 

단순하게 정리하면

시작점과 꼭 경유해야하는 간선이 주어졌을 때 해당하는 노드가

문제에서 원하는 도착점이 될 수 있는지

판단해야한다.

 

 


 

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

https://www.acmicpc.net/board/view/47684

 

글 읽기 - 이렇게 풀면 쉽지 않나요?

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

도착점 후보가 진짜로 도착점인지 확인하려면

 

시작점으로부터 경유지를 경유하고 도착점 후보에 도착한 거리와

 

시작점으로부터 도착점 후보까지의 최단 거리가 같아야한다.

 

이를 바탕으로 최단거리에 도달 했을 때 g와 h의 간선을 지났다면

 

해당 도착점후보가 도착점이 될 수 있음을 알 수 있다.

 

그래서 g-h 간선을 지났는지 여부를 따로 저장해주면서 확인하면 이 문제를 해결 할 수 있다.

 

 

 

 

다만 핵심은 priority_queue를 이용할 때

 

거리와 노드가 동일하다면 g-h간선이 지난 여부가 true인 상태가

 

우선으로 pop 되도록 설계해야 한다.

 

 

 

 

 

 


 

 

3.문제풀이코드 C++

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

struct Node {
	int x, d;
	bool ispassing;

	bool operator<(const Node& b) const {
		if (x == b.x && d == b.d) {
			return ispassing < b.ispassing;
		}
		return d > b.d;
	}

};


bool dijkstra(vector<pair<int, int> >* v, int st, int en, int g, int h) {
	bool passed = false;

	int dist[2001];
	memset(dist, 0x3f, sizeof(dist));

	priority_queue<Node> Q;
	Q.push({ st,0,0 });

	while (!Q.empty()) {
		int x = Q.top().x;
		int d = Q.top().d;
		bool p = Q.top().ispassing;

		Q.pop();

		if (dist[x] <= d) continue;
		dist[x] = d;

		if (x == en) {
			if (p) {
				passed = true;
			}

			break;
		}

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

			if (dist[nx] > nd) {
				if (p) {
					Q.push({ nx,nd,p });
				}
				else {
					if ((x == g && nx == h) || (x == h && nx == g)) {
						Q.push({ nx,nd,1 });
					}
					else {
						Q.push({ nx,nd,0 });
					}
				}
			}

		}

	}
	return passed;
}

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

	int tt;
	cin >> tt;

	for (int T = 0; T < tt; T++) {

		vector<pair<int, int> > v[2001];

		int n, m, t;
		int s, g, h;
		cin >> n >> m >> t;
		cin >> s >> g >> h;

		for (int i = 0; i < m; i++) {
			int a, b, d;
			cin >> a >> b >> d;

			v[a].push_back({ b,d });
			v[b].push_back({ a,d });
		}

		vector<int> ans;
		for (int i = 0; i < t; i++) {
			int x;
			cin >> x;


			if (dijkstra(v, s, x, g, h)) {
				ans.push_back(x);
			}

		}

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

		for (int i = 0; i < ans.size(); i++) {
			cout << ans[i] << ' ';
		}

		cout << '\n';

	}


	return 0;
}

백준 9370번

 

반응형
반응형

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

 

11779번: 최소비용 구하기 2

첫째 줄에 도시의 개수 n(1≤n≤1,000)이 주어지고 둘째 줄에는 버스의 개수 m(1≤m≤100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스

www.acmicpc.net

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

int n, m, st, en;

pair<int, int> dist[1001]; //거리 , 이전노드 저장 

vector<pair<int, int> > v[1001];

struct Node {
	int x, ex ,d;
	bool operator<(const Node& b)const {
		return d > b.d;
	}
};

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


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

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

	cin >> st >> en;
	priority_queue<Node> Q;
	Q.push({ st,-1,0 });

	vector<int> ans;


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

		if (dist[x].first <= d) continue;

		dist[x].first = d;
		dist[x].second = ex;


		if (x == en) {
			int a = en;

			while (a != -1) {
				ans.push_back(a);
				a = dist[a].second;
			}

			cout << d << '\n';
			cout << ans.size() << '\n';

			for (int i = ans.size() - 1; i >= 0; i--) {
				cout << ans[i] << ' ';
			}
			return 0;
		}


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

			if (dist[nx].first > nd) {
				Q.push({ nx,x,nd });
			}
		}
	}



	return 0;
}

백준 11779번

 

반응형
반응형

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

 

1916번: 최소비용 구하기

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그

www.acmicpc.net

 

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


int res[1001];

struct Node {
	int x, dist;

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

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

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

	int n, m, st, end;
	vector<Node> map[1001];

	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		int a, b, c;
		cin >> a >> b >> c;

		map[a].push_back({ b,c });
	}
	cin >> st >> end;

	priority_queue<Node> Q;

	Q.push({ st,0 });
	res[st] = 0;

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

		
		if (res[x] < d) continue;
		
		res[x] = d;
		if (x == end) {
			cout << d << '\n';
			return 0;
		}

		for (int i = 0; i < map[x].size(); i++) {
			int nx = map[x][i].x;
			int nd = map[x][i].dist;

			if (res[nx] > nd + d) {
				Q.push({ nx,nd + d });
			}

		}
	}

	return 0;
}

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

백준 1916

반응형
반응형

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

 

10800번: 컬러볼

첫 줄에는 공의 개수를 나타내는 자연수 N이 주어진다(1 ≤ N ≤ 200,000). 다음 N개의 줄 중 i번째 줄에는 i번째 공의 색을 나타내는 자연수 Ci와 그 크기를 나타내는 자연수 Si가 주어진다(1 ≤ Ci ≤ N

www.acmicpc.net

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

struct Ball {
	int idx, color, size;

	bool operator<(const Ball& b) const {
		if (size == b.size) return idx < b.idx;
		else return size < b.size;
	}
};

int color[200001], sum;
int ans[200001];

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

	cin >> n;
	vector<Ball> v;
	v.push_back({ 0,0,0 });

	for (int i = 1; i <= n; i++) {
		int a, b;
		cin >> a >> b;
		v.push_back({ i,a,b });
	}
	sort(v.begin(), v.end());

	for (int i = 1, j = 1; i <= n; i++) {
		while (v[i].size > v[j].size) {
			sum += v[j].size;
			color[v[j].color] += v[j].size;
			j++;
		}
		ans[v[i].idx] = sum - color[v[i].color];
	}



	for (int i = 1; i <= n; i++) {
		cout << ans[i] << '\n';
	}

	return 0;
}

백준 10800번 컬러볼

반응형
반응형

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

 

10166번: 관중석

KOI 공연장의 관중석에는 가운데에 있는 무대를 중심으로 반지름이 자연수인 동심원(중심이 같은 여러 원들) 위에 다음과 같이 좌석들이 배치되어 있다. 반지름이 1인 원 위에는 좌석이 1개, 반지

www.acmicpc.net

 

접근방법[알고리즘]

 

2차원 배열로 분수 형태를 나타낼 수 있다.

분수를 기약분수로 나타내기 위해 최대공약수를 이용해야 한다.

 

 

문제풀이코드 C++

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

int GCD(int a, int b) {
	if (a < b) swap(a, b);
	if (a % b == 0) {
		return b;
	}
	else {
		return GCD(b, a % b);
	}
}

bool ch[2001][2001];

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


	int a, b;
	cin >> a >> b;
	int ans = 1;

	for (int i = a; i <= b; i++) {
		for (int j = 1; j < i; j++) {
			int mod = GCD(i, j);
			int a = j / mod;
			int b = i / mod;
			if (ch[a][b] == 0) {
				ans++;
				ch[a][b] = 1;
			}
		}
	}


	cout << ans <<'\n';

	return 0;
}

백준 10166 메모리 및 시간 

 

반응형
반응형

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

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

접근방법[알고리즘]

1. 빙산이 몇개의 덩어리로 이루어져있는지 BFS를 이용해 개수를 센다.

2. 빙산의 개수가 2개이상이거나 0이 아니면 빙산을 한차례 녹인다.

3. 1과 2를 반복한다.

 


주의할 점

빙산이 녹아 없어지는 경우 바로 0으로 만들어버리면
다음 빙산에 영향을 줘서 틀린다.
빙산이 0이 되는 경우는 따로 저장해뒀다가 큐를 한바퀴 다 돈다음
적용 해주어야 한다.

 


문제풀이코드 C++

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

int n, m, arr[301][301] ,t;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

int Count() {
	int check[301][301];
	int ans = 1;
	memset(check, 0, sizeof(check));
	queue<pair<int, int> > Q;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (arr[i][j] > 0 && check[i][j]==0) {
				check[i][j] = ans;
				Q.push({ i,j });

				while (!Q.empty()) {
					int x = Q.front().first;
					int y = Q.front().second;
					Q.pop();

					for (int k = 0; k < 4; k++) {
						int nx = x + dx[k];
						int ny = y + dy[k];
						if (nx < 0 || nx >= n || ny < 0 || ny >= m || arr[nx][ny] == 0) continue;
						if (check[nx][ny] == 0) {
							check[nx][ny] = ans;
							Q.push({ nx,ny });
						}
					}
				}
				ans++;
			}
		}
	}
	return ans - 1;
}


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

	queue<pair<int, int> > Q;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
			if (arr[i][j] > 0) Q.push({ i,j });
		}
	}


	while (1) {
		int area = Count();
		if (area >= 2) {
			cout << t << '\n';
			return 0;
		}
		else if (area == 0) {
			cout << 0 << '\n';
			return 0;
		}

		int s = Q.size();
		//빙산이 녹아 없어지는 경우 바로 0으로 만들어버리면
		//다음 빙산에 영향을 줘서 틀린다.
		//빙산이 0이 되는 경우는 따로 저장해뒀다가 큐를 한바퀴 다 돈다음
		//적용 해주어야 한다.

		vector<pair<int, int> > melt;
		for (int i = 0; i < s; i++) {
			int x = Q.front().first;
			int y = Q.front().second;
			Q.pop();

			int cnt = 0;
			for (int j = 0; j < 4; j++) {
				int nx = x + dx[j];
				int ny = y + dy[j];
				if (nx < 0 || nx >= n || ny < 0 || ny >= m || arr[nx][ny]>0) continue;
				cnt++;
			}

			if (cnt >= arr[x][y]) {
				melt.push_back({ x,y });
			}
			else {
				arr[x][y] -= cnt;
				Q.push({ x,y });
			}
		}
		for (int i = 0; i < melt.size(); i++) {
			arr[melt[i].first][melt[i].second] = 0;
		}

		t++;
	}

	return 0;
}

백준 2573번

 

반응형
반응형

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

 

15971번: 두 로봇

2018년 강원도에서 새로운 동굴이 발견되었다. 이 동굴에는 총 N개의 넓은 방이 존재하며 좁은 통로로 서로 연결되어 있는 것으로 밝혀졌다. N개의 방은 1번부터 N번까지의 번호를 붙여 1번 방, 2번

www.acmicpc.net

 

1.문제설명

 

백준 15971번 : 두 로봇

두 로봇이 통신하기 위해 이동해야하는 최단 거리를 구해야한다.

두 로봇은 같은 노드에 있거나 서로 연결된 노드에 위치하면 통신할 수 있다.

 

 

 

 

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

처음에는 문제에 주어진 대로 로봇 두대를 놓고 한 로봇 씩 이동시키면서 

통신할 수 있는지 확인하고 그 때 이동한 거리를 계속 갱신해주면서 답을 구했는데

이러면 n이 10만이기 때문에 시간초과로 틀렸다.

 

 

문제의 조건에서

N개의 노드와 N-1의 간선이 있기 때문에

이미 지나온 노드를 재방문 할 수 없을 때

출발 지점에서 도착 지점까지 가는 경로는 무조건 하나만 나오고, 그게 최단 경로가 된다.

 

이 문제를 해결하려면

1. 두 로봇의 시작점 사이의 거리를 구한다.

2. 시작점을 이어주는 통로 중 길이가 가장 긴 간선을 구한다.

3. 답 = 시작점 사이 거리 - 가장 긴 간선 거리 

 

 

 


 

 

 

 

3.문제풀이코드 C++

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

int n, s1, s2;
vector<pair<int, int> > m[100001];

bool ch[100001];
bool flag = false;

void DFS(int x, int sum, int max_dist) {
	if (flag) return;
	if (x == s2) {
		cout << sum - max_dist << '\n';
		flag = true;
		return;
	}

	for (int i = 0; i < m[x].size(); i++) {
		int nx = m[x][i].first;
		int nd = m[x][i].second;
		if (ch[nx] == 0) {
			ch[nx] = 1;
			DFS(nx, sum + nd, max(nd,max_dist));
		}
	}

	return;
}

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

	cin >> n >> s1 >> s2;
	for (int i = 0; i < n - 1; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		m[a].push_back({ b,c });
		m[b].push_back({ a,c });
	}
	ch[s1] = 1;
	DFS(s1, 0, 0);

	return 0;
}

백준 15971번 두 로봇

DFS를 돌면서 다른 로봇의 시작점을 만나면 바로 종료해주면 된다.

 

해당 정점까지 가는 다른 방법이 존재하지 않기 때문이다.

 

 

 

반응형
반응형

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

 

2636번: 치즈

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓

www.acmicpc.net

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

int n, m, arr[103][103], ans;
queue<pair<int, int> > Q;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };


// 1. 공기 구역 BFS
// 2. 공기와 접한 치즈 사라짐
// 1, 2 반복 
bool air[103][103];
queue<pair<int, int> > airQ;


void air_spread() {
	while (!airQ.empty()) {
		int x = airQ.front().first;
		int y = airQ.front().second;
		airQ.pop();

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

			if (nx < 0 || nx >= n || ny < 0 || ny >= m || air[nx][ny] == 1) continue;
			if (arr[nx][ny] == 0) {
				airQ.push({ nx,ny });
				air[nx][ny] = 1;
			}
		}
	}
}


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

	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 1) {
				Q.push({ i,j });
			}
		}
	}

	// 맨 처음 공기인 부분 
	for (int i = 0; i < n; i++) {
		air[i][0] = 1;
		airQ.push({ i,0 });
		air[i][m - 1] = 1;
		airQ.push({ i,m - 1 });
	}

	for (int i = 0; i < m; i++) {
		air[0][i] = 1;
		airQ.push({ 0,i });
		air[n-1][i] = 1;
		airQ.push({ n-1, i});
	}


	int t = Q.size();
	while (!Q.empty()) {
		air_spread();
		t = Q.size();
		vector<pair<int, int> > melt;

		for (int q = 0; q < t; q++) {
			int x = Q.front().first;
			int y = Q.front().second;
			Q.pop();

			bool has_hole = false;
			for (int i = 0; i < 4; i++) {
				int nx = x + dx[i];
				int ny = y + dy[i];

				if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
				if (air[nx][ny] == 1) {
					melt.push_back({ x,y });
					has_hole = true;
					break;
				}
			}
			if (!has_hole) Q.push({ x,y });
		}

		for (int i = 0; i < melt.size(); i++) {
			arr[melt[i].first][melt[i].second] = 0;
			air[melt[i].first][melt[i].second] = 1;
			airQ.push({ melt[i].first, melt[i].second });
		}
		ans++;
	}

	cout << ans << '\n';
	cout << t << '\n';
	return 0;
}

백준 2636번 

 

반응형

+ Recent posts