반응형

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

 

2812번: 크게 만들기

N자리 숫자가 주어졌을 때, 여기서 숫자 K개를 지워서 얻을 수 있는 가장 큰 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

 

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

int n, k;
string str;

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

	cin >> n >> k;
	cin >> str;

	deque<char> Q;

	for (int i = 0; i < str.length(); i++) {
		while (k && !Q.empty() && Q.back() < str[i]) {
			Q.pop_back();
			k--;
		}
		Q.push_back(str[i]);
	}

	for (int i = 0; Q.size() - k; i++) {
		cout << Q.front();
		Q.pop_front();
	}

	return 0;
}

반응형
반응형

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

 

11559번: Puyo Puyo

총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다. 이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다. R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.

www.acmicpc.net

1.문제설명

......
......
......
......
......
......
......
......
.Y....
.YG...
RRYG..
RRYGG.

12 * 6 으로 Input이 주어질 때

같은 색깔인 칸이 상하좌우로 인접하여 4개 이상 있다면 모두 터트려줍니다.

 

......
......
......
......
......
......
......
......
.Y....
.YG...
..YG..
..YGG.

 

 

더이상 터질 수 있는 뿌요가 없다면

중력에 의해 공중에 있는 뿌요는 밑으로 떨어지게 됩니다.

......
......
......
......
......
......
......
......
......
..G...
.YYG..
.YYGG.

 

다시 터트리고 채워주고 반복하면서

터트리는 과정을 몇번 할 수 있는지 세면 되는 문제입니다.

 


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

이 문제는 시뮬레이션 문제로 두가지 과정을 구현해주면 됩니다.

 

1. 뿌요 터트리기

2. 뿌요 떨어트리기

 

 

뿌요 터트리기는 BFS를 돌면서 같은 뿌요가 있다면 몇개있는지 세주고 4개 이상 있다면

같은 뿌요들을 저장해준뒤 char '.'로 바꿔주면 쉽게 구현할 수 있습니다.

 

뿌요 떨어트리기는 for문을 돌면서 맨 아래칸부터 시작하여 위칸을 돌면서

뿌요가 있다면 뿌요가 없는 맨 아래칸과 바꿔주면 됩니다.

 

 

 

처음 주어지는 INPUT이 중력에 의해 떨어진 상태가 아닐수도 있기 때문에

맨 처음 뿌요를 일단 다 떨어트리고 시작해야합니다.

 


 

3.문제풀이코드 C++

 

#include <iostream>
#include <algorithm>
#include <queue>
#include <memory.h>
using namespace std;

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

void fall() {
	for (int i = 0; i < 6; i++) {
		for (int j = 11; j >= 0; j--) {
			if (arr[j][i] == '.') {
				for (int k = j - 1; k >= 0; k--) {
					if (arr[k][i] != '.') {
						swap(arr[j][i], arr[k][i]);
						break;
					}
				}
			}
		}
	}
}


bool bomb() {
	bool ch[12][6];
	memset(ch, 0, sizeof(ch));
	queue<pair<int, int> > Q;
	bool bombed = false;

	for (int i = 0; i < 12; i++) {
		for (int j = 0; j < 6; j++) {

			if (ch[i][j] == 0 && arr[i][j] != '.') {

				vector<pair<int, int> > v;
				char color = arr[i][j];
				int cnt = 1;
				ch[i][j] = 1;
				v.push_back({ i,j });
				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 >= 12 || ny < 0 || ny >= 6 || ch[nx][ny] == 1) continue;
						if (arr[nx][ny] == color) {
							cnt++;
							ch[nx][ny] = 1;
							Q.push({ nx,ny });
							v.push_back({ nx,ny });
						}
					}
				}

				if (cnt >= 4) {
					bombed = true;
					for (int k = 0; k < v.size(); k++) {
						arr[v[k].first][v[k].second] = '.';
					}
				}
			}
		}
	}

	return bombed;
}



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


	for (int i = 0; i < 12; i++) {
		cin >> arr[i];
	}
	// 필드에 뿌요를 모두 두고 일단 떨어트린다. 
	fall();

	//1.터트린다 - 개수 0이면 끝
	//2. 내린다
	//1.2 반복
	int ans = 0;

	while (1) {
		if (bomb()) {
			ans++;
			fall();
		}
		else {
			break;
		}
	}

	cout << ans << '\n';

	return 0;
}

백준 11559번 시간 및 메모리 

 

반응형
반응형

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

 

16918번: 봄버맨

첫째 줄에 R, C, N (1 ≤ R, C, N ≤ 200)이 주어진다. 둘째 줄부터 R개의 줄에 격자판의 초기 상태가 주어진다. 빈 칸은 '.'로, 폭탄은 'O'로 주어진다.

www.acmicpc.net

1.문제설명

폭탄은 3초가 지나야 터진다.

폭탄이 터지면 폭탄이 있던 자리와 인접한 상하좌우칸이 .이 된다.

폭탄이 터지는 인접 상하좌우에 폭탄이 있을 경우 상하좌우에 있던 폭탄은 그냥 사라진다.

 

 

2.접근방법

3초가 되는 폭탄을 따로 배열이나 벡터에 저장했다가

각각 터트려야 쉽게 구현할 수 있다.

 

만약 3초가 지난 폭탄을 따로 저장하지 않고 순차적으로 터트릴 경우

인접한 3초 폭탄이 사라져 다른 결과를 얻게 된다.

 

다음 표에서 3이 써있는 폭탄은 이제 터지는 폭탄이라고 두고

O는 아직 터지지 않는 폭탄이라 생각하자.

3 3 O
O O O
O O O

 

그냥 무지성으로 3인 폭탄을 for문으로 돌며 터트리면 다음과 같은 결과를 얻는다

X X O
X O O
O O O

오른쪽에 있던 3폭탄이 터지지 못하고 그냥 묻혀버리고 만다.

다른 벡터에 3인 폭탄의 좌표를 모두 저장한 후 벡터에서 for문을 돌면서 터트리면 

X X X
X X O
O O O

이런 옳은 결과를 얻을 수 있다.

 

많은 시뮬레이션 문제에서 이렇게 정보를 저장한 후 실행하는 방법이 유용하게 쓰인다.

 

단순히 순차적으로 돌다보면 문제가 생기는 경우가 많다.

 

 


3.문제풀이코드 C++

 

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

int r, c, n, T;

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


void print() {
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			if (a[i][j] == -1) {
				cout << '.';
			}
			else cout << 'O';
		}
		cout << '\n';
	}
}

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

	cin >> r >> c >> n;

	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			char tmp;
			cin >> tmp;
			if (tmp == 'O') {
				a[i][j] = 0;
			}
			else {
				a[i][j] = -1;
			}
		}
	}
	
	if (T == n) {
		print();
		return 0;
	}


	T++;
	// 첫 1초 아무것도 안함 
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			if (a[i][j] == 0) {
				a[i][j]++;
			}
		}
	}
	if (T == n) {
		print();
		return 0;
	}

	
	T++;
	//2초 모든칸 폭탄 설치 
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			a[i][j]++;
		}
	}
	if (T == n) {
		print();
		return 0;
	}



	while(T<n) {

		T++;
		vector<pair<int, int> > v;
		
	
		// 아무것도 안함 
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				if (a[i][j] >= 0) a[i][j]++;
				if (a[i][j] == 3) {
					v.push_back({ i,j });
				}
			}
		}


		for (int i = 0; i < v.size(); i++) {
			a[v[i].first][v[i].second] = -1;
			for (int k = 0; k < 4; k++) {
				int nx = v[i].first + dx[k];
				int ny = v[i].second + dy[k];
				if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
				a[nx][ny] = -1;
			}
		}

		v.clear();
		if (T == n) break;


		T++;


		// 폭탄 설치 
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				a[i][j]++;
				if (a[i][j] == 3) v.push_back({ i,j });
			}
		}
		for (int i = 0; i < v.size(); i++) {
			a[v[i].first][v[i].second] = -1;
			for (int k = 0; k < 4; k++) {
				int nx = v[i].first + dx[k];
				int ny = v[i].second + dy[k];
				if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
				a[nx][ny] = -1;

			}
		}


	}

	
	print();

	return 0;
}

백준 16918 봄버맨

반응형
반응형

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

 

17144번: 미세먼지 안녕!

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사

www.acmicpc.net

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

int r, c, t, arr[51][51], cleaner;
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };


struct Dust {
	int x, y, q;
};


int ans() {
	int cnt = 0;
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			if (arr[i][j] > 0) {
				cnt += arr[i][j];
			}
		}
	}
	return cnt;
}


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

	cin >> r >> c >> t;


	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == -1) {
				cleaner = i;
			}
		}
	}

	int clean_up = cleaner - 1;
	int clean_down = cleaner;

	//1.미세먼지 확산
	//2. 공기 청정기 이동 
	for (int T = 1; T <= t; T++) {

		vector<Dust> d;

		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				if (arr[i][j] >= 5) {
					d.push_back({ i,j,arr[i][j] });
				}
			}
		}

		//확산 
		for (int i = 0; i < d.size(); i++) {
			int spread = 0;
			if (d[i].q >= 5) {
				for (int k = 0; k < 4; k++) {
					int nx = d[i].x + dx[k];
					int ny = d[i].y + dy[k];

					if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
					if (arr[nx][ny] == -1)continue;
					arr[nx][ny] += (d[i].q / 5);
					spread++;

				}
				arr[d[i].x][d[i].y] -= (d[i].q / 5) * spread;
			}
		}

		// 공기청정기 작동 
		for (int i = clean_up - 1; i >= 0; i--) {
			arr[i + 1][0] = arr[i][0];
		}

		for (int i = clean_down; i < r; i++) {
			arr[i][0] = arr[i + 1][0];

		}

		for (int i = 0; i < c-1; i++) {
			arr[0][i] = arr[0][i + 1];
			arr[r - 1][i] = arr[r - 1][i + 1];
		}

		for (int i = 0; i < clean_up ; i++) {
			arr[i][c - 1] = arr[i + 1][c - 1];
		}

		for (int i = r-1; i > clean_down; i--) {
			arr[i][c - 1] = arr[i - 1][c - 1];
		}

		for (int i = c - 1; i > 1; i--) {
			arr[clean_up][i] = arr[clean_up][i - 1];
			arr[clean_down][i] = arr[clean_down][i - 1];
		}
		arr[clean_up][1] = 0;
		arr[clean_down][1] = 0;


		arr[clean_up][0] = -1;
		arr[clean_down][0] = -1;


	}

	int ans = 0;
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < c; j++) {
			if (arr[i][j] > 0) ans += arr[i][j];
		}
	}

	cout << ans << '\n';

	return 0;
}

백준 17144번 미세먼지 안녕!

반응형
반응형

 

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

 

17143번: 낚시왕

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

www.acmicpc.net

1. 문제설명

낚시왕이 되는 일은 꽤 어려운 일인지도 모릅니다.

 

백준 17143번 낚시왕

어부는 오른쪽 열로 한칸 씩 이동하면서 

어부가 서있는 열에서 가장 가까운 상어를 잡습니다.

 

상어는 어부가 한칸 움직일 때마다 각각의 방향과 속도로 움직입니다.

만약 모든 상어가 움직인 후 같은 칸에 상어가 두마리 있을 경우 크기가 큰 상어만 남습니다.

 

어부가 끝까지 이동한 후 잡은 상어의 크기 합을 출력하면 됩니다.

 


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

이 문제를 해결하기 위해 특별히 필요한 알고리즘은 없습니다.

 

문제에서 제시한 조건 대로 구현하면 됩니다.

 

1. 어부가 오른쪽 열로 한칸 움직이고 가장 가까운 상어를 잡는다.

2. 상어 모두 각각 움직인다.

3. 겹치는 상어가 있으면 크기가 큰 것만 남긴다.

 

상어의 움직임을 구현하는 게 이 문제의 핵심입니다.

 

Input

상어의 정보는 다섯 정수 r, c, s, d, z (1 ≤ r ≤ R, 1 ≤ c ≤ C, 0 ≤ s ≤ 1000, 1 ≤ d ≤ 4, 1 ≤ z ≤ 10000) 로 이루어져 있다. (r, c)는 상어의 위치, s는 속력, d는 이동 방향, z는 크기이다.

 

전체 격자판 최대 크기는 100*100인데

상어의 속도는 1000이 최댓값이기 때문에

1000을 그대로 사용한다면 불필요한 움직임이 많이 포함됩니다.

 

상어가 열이나 행을 왕복하는데 필요한 거리는 r, c 값에 따라 고정되어 있기 때문에

연산을 통해 속도를 빼줄 수 있습니다.

if (d <= 2) s %= (r - 1) * 2;
else s %= (c - 1) * 2;

(r-1)*2 번이나 (c-1)*2 번 왔다갔다 하면 상어가 제자리에 놓이기 때문에

불필요한 연산을 줄여줄 수 있습니다.

이 과정을 거치지 않으면 시간초과가 납니다.

 

 

 


3.문제풀이코드 C++

 

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

int r, c, m, ans;

struct Shark {
	bool isin = 0;
	int s = 0, d = 0, z = 0;
};

Shark ch[103][103];

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

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

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

		//상어의 반복움직임 제거
		if (d <= 2) s %= (r - 1) * 2;
		else s %= (c - 1) * 2;

		ch[a][b] = { 1,s,d,z };
	}


	for (int i = 1; i <= c; i++) {

		Shark moved[103][103];

		//해당 열에서 상어 잡기 
		for (int j = 1; j <= r; j++) {
			if (ch[j][i].isin) {
				ans += ch[j][i].z;
				ch[j][i] = { 0,0,0,0 };
				break;
			}
		}

		// 상어 이동 
		for (int j = 1; j <= r; j++) {
			for (int k = 1; k <= c; k++) {
				if (ch[j][k].isin) {
					int nx = j;
					int ny = k;

					for (int q = 0; q < ch[j][k].s; q++) {
						if (ch[j][k].d == 1) {
							//벽 만난 경우 방향전환
							if (nx == 1) {
								ch[j][k].d = 2;
								q--;
								continue;
							}
							nx += dx[0];
							ny += dy[0];

						}
						else if (ch[j][k].d == 2) {
							if (nx == r) {
								ch[j][k].d = 1;
								q--;
								continue;
							}

							nx += dx[1];
							ny += dy[1];

						}
						else if (ch[j][k].d == 3) {
							if (ny == c) {
								ch[j][k].d = 4;
								q--;
								continue;
							}
							nx += dx[2];
							ny += dy[2];

						}
						else if (ch[j][k].d == 4) {
							if (ny == 1) {
								ch[j][k].d = 3;
								q--;
								continue;
							}
							nx += dx[3];
							ny += dy[3];
						}

					}
					// 같은 칸에 상어 두마리가 있는 경우
					// 크키가 큰 상어만 남긴다.
					if (moved[nx][ny].isin) {
						if (moved[nx][ny].z < ch[j][k].z) {
							moved[nx][ny] = { 1,ch[j][k].s,ch[j][k].d,ch[j][k].z };
						}
					}
					else {
						moved[nx][ny] = { 1,ch[j][k].s,ch[j][k].d,ch[j][k].z };
					}

				}
			}
		}
		// moved 배열에 있는 값을 ch배열로 복사해주고 
		// ch배열을 통해 어부가 이동한후 다시 계산하도록 해준다.
		memcpy(&ch, &moved, sizeof(moved));
	}

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

백준 17143번 낚시왕

 

 

백준 17143번 낚시왕 테스트케이스 및 반례

50 50 19
4 9 21 1 999
50 50 4 4 500
50 49 222 3 200
50 48 12 2 45
50 47 36 1 900
2 3 20 3 444
4 8 4 2 49
3 3 40 4 50
2 2 460 2 4444
48 23 500 3 12
1 1 200 1 123
44 44 123 3 125
44 40 222 3 17
40 44 333 3 57
18 40 1 1 4
3 10 50 2 406
1 36 177 4 50
1 46 120 4 7
1 50 28 4 54
정답 7718

 

반응형
반응형

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

 

14890번: 경사로

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

www.acmicpc.net

1.문제설명

백준 14890번

갈 수 있는 길인지 판단하고(한 줄의 모든 숫자가 같은 지),

경사로를 둬서 갈 수 있는 길로 만들 수 있는지 확인해야한다.

 

 


 

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

 

먼저 모든 숫자가 같은지 확인하고,

모든 숫자가 같지 않다면

 

경사로를 둬서 갈 수 있는 길인지 확인하기 위해서

각 행을 해당 숫자와 해당 숫자의 개수로 표현했다.

 

6 2
3 3 3 3 3 3
2 3 3 3 3 3
2 2 2 3 2 3
1 1 1 2 2 2
1 1 1 3 3 1
1 1 2 3 3 2

이런 입력의 경우 가로 행만 살펴보면

6 2                 Num : Count
3 3 3 3 3 3        -> 3 : 6
2 3 3 3 3 3           2 : 1 , 3 : 5
2 2 2 3 2 3           2 : 3, 3 : 1 , 2 : 1 , 3 : 1
1 1 1 2 2 2           1 : 3, 2 : 3
1 1 1 3 3 1           1 : 3 , 3 : 2 , 1 : 1 
1 1 2 3 3 2           1 : 2, 2 : 1 , 3 : 2 , 2 : 1

이렇게 표현 할 수 있다

이렇게 한 줄에 대한 정보를 표현하고

L 변수를 이용해서 경사로를 둘 수 있는 지 없는 지 판단 할 수 있다

 

L = 2 일 때

3 : 6 은 모두 같은 숫자이므로 길이다.

 

2 : 1 , 3 : 5

이 줄에는 경사로를 둬서 길을 만들 수 없다.

숫자가 작은 부분의 길이가 L보다 작기 때문이다.

 

2 : 3 , 3 : 1, 2 :1 , 3: 1

이 줄도 2:1 이므로 2의 길이가 L보다 작으므로 길이 될 수 없다

 

1 : 3 , 2 : 3

1의 길이가 3이므로 L보다 커서 길이 될 수 있다.

 

 

 

예외

L이 동일하게 2일 때

 

3 3 2 2 3 3

이런 경우는 2에 경사로를 한 번 두면 더이상 경사로를 또 둘 수 없기 때문에 길이 될 수 없다.

 

 

 

이러한 경우들을 코드로 구현해보면

 

void Count(int arr[101][101]) {
	for (int i = 1; i <= n; i++) {
		int val = 0, cnt = 0;
		
        //v 벡터에 한 줄 정보 표현 
		vector<pair<int, int> > v;
		for (int j = 1; j <= n; j++) {
			if (j == 1) {
				val = arr[i][j];
				cnt = 1;
				continue;
			}

			if (arr[i][j] == val) {
				cnt++;
			}
			else {
				v.push_back({ val,cnt });
				val = arr[i][j];
				cnt = 1;
			}
		}
		v.push_back({ val,cnt });
		
        // 모두 같은 숫자인 경우 
		if (v.size() == 1) {
			ans++;
			continue;
		}

		//경사로 추가해서 길을 만들 수 있는지 확인 
		bool canmake = true;

		for (int k = 0; k < v.size() - 1; k++) {
        	// 높이 차이가 1보다 크면 길이 될 수 없다.
			if (abs(v[k].first - v[k + 1].first) > 1) {
				canmake = false;
				break;
			}


			if (v[k].first < v[k + 1].first) {
				if (v[k].second < l) {
					canmake = false;
					break;
				}
			}
			else {
				if (v[k + 1].second < l) {
					canmake = false;
					break;
				}
				else {
                	// 332233 같은 경우를 위해 경사로를 두면 count에서 빼준다.
					v[k + 1].second -= l;
				}

			}
		}
		if (canmake) ans++;
	}

}

 


 

3.문제풀이코드 C++

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

int n, l, arr[101][101], arr2[101][101], ans;

void Count(int arr[101][101]) {
	for (int i = 1; i <= n; i++) {
		int val = 0, cnt = 0;

		vector<pair<int, int> > v;
		for (int j = 1; j <= n; j++) {
			if (j == 1) {
				val = arr[i][j];
				cnt = 1;
				continue;
			}

			if (arr[i][j] == val) {
				cnt++;
			}
			else {
				v.push_back({ val,cnt });
				val = arr[i][j];
				cnt = 1;
			}
		}
		v.push_back({ val,cnt });

		if (v.size() == 1) {
			ans++;
			continue;
		}

		//경사로 추가해서 길을 만들 수 있는지 확인 
		bool canmake = true;

		for (int k = 0; k < v.size() - 1; k++) {
			if (abs(v[k].first - v[k + 1].first) > 1) {
				canmake = false;
				break;
			}

			if (v[k].first < v[k + 1].first) {
				if (v[k].second < l) {
					canmake = false;
					break;
				}
			}
			else {
				if (v[k + 1].second < l) {
					canmake = false;
					break;
				}
				else {
					v[k + 1].second -= l;
				}

			}
		}
		if (canmake) ans++;
	}

}

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

	cin >> n >> l;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> arr[i][j];
			arr2[j][i] = arr[i][j];
		}
	}
	
	Count(arr);
	Count(arr2);


	cout << ans << '\n';


	return 0;

}

14890번 경사로

 

이 문제에서 가로방향 길과 세로방향 길의 개수를 모두 세야한다.

 

하지만 가로방향이나 세로방향이나 길을 세는 방법이 동일하기 때문에

 

arr2 배열을 arr과 대칭적으로 입력해주어 동일하게 Count 하면

 

쉽게 답을 구할 수 있다.

반응형
반응형

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

 

11724번: 연결 요소의 개수

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주

www.acmicpc.net

1. 문제설명

무방향 그래프가 주어지고 노드와 간선간의 정보가 주어졌을 때

연결 요소 (Connected Component)의 개수를 구하는 문제입니다.

 

연결 요소의 개수는

서로 연결되어 있는 집합이 몇개인 지 구해야 합니다.

 

Connected Component

 

위 그림과 같은 경우 Connected Component는 2개 입니다.

 

 

 

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

 

먼저 떠오르는 해결 방법은

모든 노드 간선 정보를 바탕으로 그래프를 만들고

BFS나 DFS로 탐색하면서 방문한 노드를 체크하면서

방문하지 않은 새로운 노드를 발견할 때마다 정답으로 출력할 변수에 +1을 해주면 구할 수 있습니다.

 

 

한번 더 나아가면 Union & Find 알고리즘을 이용해

서로 연결되어있는 노드는 같은 집합으로 분류해주고

부모노드의 개수를 세면 집합의 개수를 알 수 있습니다.

Union & Find 알고리즘을 이용하면 BFS나 DFS보다 시간을 절약해서 풀 수 있습니다.

 

 

 

3.문제풀이코드 C++

 

1. Union & Find C++

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

int n, m , unf[1001], ans;

int Find(int a) {
	if (a == unf[a]) {
		return a;
	}
	else {
		return unf[a] = Find(unf[a]);
	}
}

void Union(int a, int b) {
	a = Find(a);
	b = Find(b);

	if (a > b) {
		swap(a, b);
	}

	if (a != b) {
		unf[a] = b;
	}
}

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

	cin >> n >> m;

	for (int i = 0; i <= 1000; i++) {
		unf[i] = i;
	}

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

	// 부모 노드의 개수 == 같은 집합의 개수
	for (int i = 1; i <= n; i++) {
		if (unf[i] == i) ans++;
	}
	cout << ans << '\n';



	return 0;

}

11724 Union&amp;Find

 

 

2. BFS

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

int n, m;

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

	cin >> n >> m;

	vector<int> map[1001];

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

		map[a].push_back(b);
		map[b].push_back(a);
	}
	int ans = 0;
	queue<int> Q;
	for (int i = 1; i <= n; i++) {
		if (!ch[i]) {
			ans++;
			ch[i] = 1;
			Q.push(i);
			while (!Q.empty()) {
				int x = Q.front();
				Q.pop();
				for (int j = 0; j < map[x].size(); j++) {
					if (ch[map[x][j]] == 0) {
						ch[map[x][j]] = 1;
						Q.push(map[x][j]);
					}
				}
			}
		}
	}

	cout << ans << '\n';

	return 0;

}

11724 BFS

 

 

 

 

 

반응형
반응형

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

 

14888번: 연산자 끼워넣기

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 

www.acmicpc.net

 

 

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

int n, arr[12], op[4], max_ans = INT_MIN, min_ans = INT_MAX;

void DFS(int x, int res) {

	if (x == n - 1) {
		max_ans = max(max_ans,res);
		min_ans = min(min_ans,res);
	}

	for (int i = 0; i < 4; i++) {
		if (op[i] > 0) {
			op[i]--;

			if (i == 0) {
				DFS(x + 1, res + arr[x + 1]);
			}
			else if (i == 1) {
				DFS(x + 1, res - arr[x + 1]);

			}
			else if (i == 2) {
				DFS(x + 1, res * arr[x + 1]);

			}
			else if (i == 3) {
				DFS(x + 1, res / arr[x + 1]);
			}
			op[i]++;
		}
	}

}


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


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

	for (int i = 0; i < 4; i++) {
		cin >> op[i];
	}

	DFS(0, arr[0]);

	cout << max_ans << '\n';
	cout << min_ans << '\n';


	return 0;
	
}

백준 14888번 연산자끼워넣기

반응형

+ Recent posts