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

 

2644번: 촌수계산

사람들은 1, 2, 3, …, n (1 ≤ n ≤ 100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어

www.acmicpc.net

문제

우리 나라는 가족 혹은 친척들 사이의 관계를 촌수라는 단위로 표현하는 독특한 문화를 가지고 있다. 이러한 촌수는 다음과 같은 방식으로 계산된다. 기본적으로 부모와 자식 사이를 1촌으로 정의하고 이로부터 사람들 간의 촌수를 계산한다. 예를 들면 나와 아버지, 아버지와 할아버지는 각각 1촌으로 나와 할아버지는 2촌이 되고, 아버지 형제들과 할아버지는 1촌, 나와 아버지 형제들과는 3촌이 된다.

여러 사람들에 대한 부모 자식들 간의 관계가 주어졌을 때, 주어진 두 사람의 촌수를 계산하는 프로그램을 작성하시오.

입력

사람들은 1, 2, 3, …, n (1 ≤ n ≤ 100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다.

각 사람의 부모는 최대 한 명만 주어진다.

출력

입력에서 요구한 두 사람의 촌수를 나타내는 정수를 출력한다. 어떤 경우에는 두 사람의 친척 관계가 전혀 없어 촌수를 계산할 수 없을 때가 있다. 이때에는 -1을 출력해야 한다.

예제 입력 1 복사

9
7 3
7
1 2
1 3
2 7
2 8
2 9
4 5
4 6

예제 출력 1 복사

3

예제 입력 2 복사

9
8 6
7
1 2
1 3
2 7
2 8
2 9
4 5
4 6

예제 출력 2 복사

-1

풀이

  • 그래프가 연결되어 있을 경우 dfs를 실행하고 찾으려고 한 정점에 다다랐을 때 실행횟수를 저장하여 출력

코드

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

#define MAX 101

vector<int> vec[MAX];
bool visited[MAX];

int n, m, person1, person2;
int result = -1;

void Dfs(int vertex1, int vertex2, int cnt)
{
	visited[vertex1] = true;

	// 찾으면 횟수 저장
	if (vertex1 == vertex2)
	{
		result = cnt;
		return;
	}

	for (int i = 0; i < vec[vertex1].size(); i++)
	{
		int next = vec[vertex1][i];
		
		if (!visited[next])
		{
			Dfs(next, vertex2, cnt + 1);
		}
	}
}

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

	cin >> n >> person1 >> person2 >> m;

	for (int i = 0; i < m; i++)
	{
		int from, to;
		cin >> from >> to;
		vec[from].push_back(to);
		vec[to].push_back(from);
	}

	memset(visited, 0, sizeof(visited));
	Dfs(person1, person2, 0);
	cout << result;

	return 0;
}

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

 

2178번: 미로 탐색

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

www.acmicpc.net

문제

N×M크기의 배열로 표현되는 미로가 있다.

1 0 1 1 1 1
1 0 1 0 1 0
1 0 1 0 1 1
1 1 1 0 1 1

미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.

위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.

입력

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

출력

첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.

예제 입력 1 복사

4 6
101111
101010
101011
111011

예제 출력 1 복사

15

예제 입력 2 복사

4 6
110110
110110
111111
111101

예제 출력 2 복사

9

예제 입력 3 복사

2 25
1011101110111011101110111
1110111011101110111011101

예제 출력 3 복사

38

예제 입력 4 복사

7 7
1011111
1110001
1000001
1000001
1000001
1000001
1111111

예제 출력 4 복사

13

풀이

  • 미로가 주어졌을 때 갈 수 있는 곳이 있을 때마다 이동 횟수를 증가시키면 되는 문제이다.
  • 시작점이 주어져있기 때문에 가장 첫 번째 칸의 좌표를 넘겨 BFS 탐색을 진행한다.

코드

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

#define MAX 101
#define _X first
#define _Y second

int maze[MAX][MAX];
int visited[MAX][MAX];

int N, M;
int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, -1, 1 };
queue<pair<int, int>> q;

void Bfs(int x, int y)
{
	visited[x][y] = 1;

	while (!q.empty())
	{
		pair<int, int> cur = q.front();
		q.pop();
		int curX = cur._X;
		int curY = cur._Y;

		for (int i = 0; i < 4; i++)
		{
			int nx = cur._X + dx[i];
			int ny = cur._Y + dy[i];

			// 범위 벗어나거나 지나갈 수 없는 곳, 방문한 곳은 처리 X
			if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue;
			if (maze[nx][ny] == 0 || visited[nx][ny] != 0) continue;
			q.push({ nx, ny });
			visited[nx][ny] = visited[curX][curY] + 1;
		}
	}

	// (N, M)에 도달했을 때의 값 출력
	cout << visited[N - 1][M - 1];
}

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

	cin >> N >> M;

	for (int i = 0; i < N; i++)
	{
		string str;
		cin >> str;
		for (int j = 0; j < M; j++)
		{
			maze[i][j] = str[j] - '0';
		}
	}

	memset(visited, 0, sizeof(visited));

	q.push({ 0, 0 });
	Bfs(0, 0);

	return 0;
}

'C++ > BFS, DFS' 카테고리의 다른 글

[C++] 백준 11724 - 연결 요소의 개수  (0) 2022.12.26
[C++] 백준 2644 - 촌수계산  (0) 2022.12.26
[C++] 백준 2606 - 바이러스  (0) 2022.12.25
[C++] 백준 7569 - 토마토 (3차원)  (0) 2022.12.12
[C++] 백준 7576 - 토마토  (0) 2022.12.11

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

 

2606번: 바이러스

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어

www.acmicpc.net

문제

신종 바이러스인 웜 바이러스는 네트워크를 통해 전파된다. 한 컴퓨터가 웜 바이러스에 걸리면 그 컴퓨터와 네트워크 상에서 연결되어 있는 모든 컴퓨터는 웜 바이러스에 걸리게 된다.

예를 들어 7대의 컴퓨터가 <그림 1>과 같이 네트워크 상에서 연결되어 있다고 하자. 1번 컴퓨터가 웜 바이러스에 걸리면 웜 바이러스는 2번과 5번 컴퓨터를 거쳐 3번과 6번 컴퓨터까지 전파되어 2, 3, 5, 6 네 대의 컴퓨터는 웜 바이러스에 걸리게 된다. 하지만 4번과 7번 컴퓨터는 1번 컴퓨터와 네트워크상에서 연결되어 있지 않기 때문에 영향을 받지 않는다.

어느 날 1번 컴퓨터가 웜 바이러스에 걸렸다. 컴퓨터의 수와 네트워크 상에서 서로 연결되어 있는 정보가 주어질 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어진다. 이어서 그 수만큼 한 줄에 한 쌍씩 네트워크 상에서 직접 연결되어 있는 컴퓨터의 번호 쌍이 주어진다.

출력

1번 컴퓨터가 웜 바이러스에 걸렸을 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 첫째 줄에 출력한다.

예제 입력 1 복사

7
6
1 2
2 3
1 5
5 2
5 6
4 7

예제 출력 1 복사

4

풀이

  • 벡터 이용하여 인접리스트 구현 후 DFS 실행

코드

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

#define MAX 101

vector<int> vec[MAX];	// 인접리스트
bool visited[MAX];		// 방문처리 배열

int comp, edge, cnt;

// 재귀 DFS 사용
void Dfs(int v)
{
	visited[v] = true;	// 방문처리
	
	// 컴퓨터와 연결되어 있는 수만큼 반복하고 카운트 증가
	for (int i = 0; i < vec[v].size(); i++)
	{
		int next = vec[v][i];

		if (visited[next] == false)
		{
			Dfs(next);
			cnt++;
		}
	}
}

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

	cin >> comp;
	cin >> edge;

	// 인접 리스트에 값 집어넣기
	for (int i = 0; i < edge; i++)
	{
		int from, to;
		cin >> from >> to;

		vec[from].push_back(to);
		vec[to].push_back(from);
	}

	// 방문 배열 초기화 후 DFS 실행
	memset(visited, 0, sizeof(visited));
	Dfs(1);
	cout << cnt;;

	return 0;
}

'C++ > BFS, DFS' 카테고리의 다른 글

[C++] 백준 2644 - 촌수계산  (0) 2022.12.26
[C++] 백준 2178 - 미로 탐색  (0) 2022.12.25
[C++] 백준 7569 - 토마토 (3차원)  (0) 2022.12.12
[C++] 백준 7576 - 토마토  (0) 2022.12.11
[C++] 백준 5014 - 스타트 링크  (0) 2022.12.06

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

 

7568번: 덩치

우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A 와 B의 덩

www.acmicpc.net

문제

우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A 와 B의 덩치가 각각 (x, y), (p, q)라고 할 때 x > p 그리고 y > q 이라면 우리는 A의 덩치가 B의 덩치보다 "더 크다"고 말한다. 예를 들어 어떤 A, B 두 사람의 덩치가 각각 (56, 177), (45, 165) 라고 한다면 A의 덩치가 B보다 큰 셈이 된다. 그런데 서로 다른 덩치끼리 크기를 정할 수 없는 경우도 있다. 예를 들어 두 사람 C와 D의 덩치가 각각 (45, 181), (55, 173)이라면 몸무게는 D가 C보다 더 무겁고, 키는 C가 더 크므로, "덩치"로만 볼 때 C와 D는 누구도 상대방보다 더 크다고 말할 수 없다.

N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 "큰 덩치"의 사람의 수로 정해진다. 만일 자신보다 더 큰 덩치의 사람이 k명이라면 그 사람의 덩치 등수는 k+1이 된다. 이렇게 등수를 결정하면 같은 덩치 등수를 가진 사람은 여러 명도 가능하다. 아래는 5명으로 이루어진 집단에서 각 사람의 덩치와 그 등수가 표시된 표이다.

이름(몸무게, 키)덩치 등수
A (55, 185) 2
B (58, 183) 2
C (88, 186) 1
D (60, 175) 2
E (46, 155) 5

위 표에서 C보다 더 큰 덩치의 사람이 없으므로 C는 1등이 된다. 그리고 A, B, D 각각의 덩치보다 큰 사람은 C뿐이므로 이들은 모두 2등이 된다. 그리고 E보다 큰 덩치는 A, B, C, D 이렇게 4명이므로 E의 덩치는 5등이 된다. 위 경우에 3등과 4등은 존재하지 않는다. 여러분은 학생 N명의 몸무게와 키가 담긴 입력을 읽어서 각 사람의 덩치 등수를 계산하여 출력해야 한다.

입력

첫 줄에는 전체 사람의 수 N이 주어진다. 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다.

출력

여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다. 단, 각 덩치 등수는 공백문자로 분리되어야 한다.

제한

  • 2 ≤ N ≤ 50
  • 10 ≤ x, y ≤ 200

예제 입력 1 복사

5
55 185
58 183
88 186
60 175
46 155

예제 출력 1 복사

2 2 1 2 5

풀이

  • 몸무게와 키를 페어로 만들어 벡터에 넣고 두 값이 모두 작을 경우에만 순위를 증가시켜 출력한다.

코드

#include <iostream>
#include <vector>

using namespace std;

int N, weight, height;
vector<pair<int, int>> v;

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

	cin >> N;
	for (int i = 0; i < N; i++)
	{
		cin >> weight >> height;
		v.push_back({ weight, height });
	}

	for (int i = 0; i < N; i++)
	{
		int rank = 1;
		for (int j = 0; j < N; j++)
		{
        	// 몸무게와 키가 모두 작을 경우에만 순위 증가시킨다.
			if (v[i].first < v[j].first && v[i].second < v[j].second)
			{
				rank++;
			}
		}
		cout << rank << " ";
	}

	return 0;
}

'C++ > Brute Force' 카테고리의 다른 글

[C++] 백준 2231 - 분해합  (0) 2022.12.16
[C++] 백준 1018 - 체스판 다시 칠하기  (0) 2022.12.16
[C++] 백준 2798 - 블랙잭  (1) 2022.12.12

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

 

2231번: 분해합

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이

www.acmicpc.net

문제

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 따라서 245는 256의 생성자가 된다. 물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 반대로, 생성자가 여러 개인 자연수도 있을 수 있다.

자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

출력

첫째 줄에 답을 출력한다. 생성자가 없는 경우에는 0을 출력한다.

예제 입력 1 복사

216

예제 출력 1 복사

198

 


풀이

  • sum: 수와 자리 수를 더할 변수, temp: 자리수를 구할 변수
  • N의 분해합이 될 수 있는 수를 for문을 이용하여 1부터 N까지 모두 검사 -> 브루트 포스
  • 현재 인덱스를 sum과 temp 변수에 저장하고 인덱스를 10으로 나눈 나머지 값을 더한 뒤, 10으로 나누었다. -> 모든 자리수를 더하기 위해 % 연산자를 이용하여 1의 자리 수를 구하고, 10으로 나눠 1의 자리 제거
  • temp를 10으로 나누었을 때 0보다 클 경우(모든 자리수를 다 더하지 않았을 때) 위의 과정을 반복한다.
  • 검사 도중 어떤 수가 N과 같으면 for문을 벗어난다.

 

  • ex) 인덱스 i가 198일 경우 

1. temp: 198, sum: 198

- temp를 10으로 나눈 나머지를 sum 변수에 더한다. -------> temp: 198 % 10 = 8 ======>  sum:198 + 8 = 206

- temp를 10으로 나눈다. --------> temp / 10 = 198 / 10 = 19

 

2. temp: 19, sum: 206

- sum: 206 + (19 % 10) = 206 + 9 = 215, temp: 19 / 10 = 1

 

3. temp: 1, sum 215

- sum: 215 + (1 % 10) = 215 + 1 = 216, temp: 1 / 10 = 0

 

4. temp가 0이 되어 while문 벗어남. sum이 입력한 값의 분해합이라면 반복문 빠져나오고 아니면 인덱스 증가하여 계속 검사한다.

 

코드

#include <iostream>

using namespace std;

int N;

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

	cin >> N;

	for (int i = 1; i < N; i++)
	{
		int temp = i;
		int sum = i;

		while (temp > 0)
		{
			sum += temp % 10;
			temp /= 10;
		}

		if (sum == N)
		{
			cout << i;
			return 0;
		}
	}
	cout << 0;
	return 0;
}

'C++ > Brute Force' 카테고리의 다른 글

[C++] 백준 7568 - 덩치  (1) 2022.12.16
[C++] 백준 1018 - 체스판 다시 칠하기  (0) 2022.12.16
[C++] 백준 2798 - 블랙잭  (1) 2022.12.12

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

 

1018번: 체스판 다시 칠하기

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

www.acmicpc.net

 
문제

지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M×N 크기의 보드를 찾았다. 어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 지민이는 이 보드를 잘라서 8×8 크기의 체스판으로 만들려고 한다.

체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.

보드가 체스판처럼 칠해져 있다는 보장이 없어서, 지민이는 8×8 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 당연히 8*8 크기는 아무데서나 골라도 된다. 지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

출력

첫째 줄에 지민이가 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.

예제 입력 1 복사

8 8
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBBBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW

예제 출력 1 복사

1

예제 입력 2 복사

10 13
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
WWWWWWWWWWBWB
WWWWWWWWWWBWB

예제 출력 2 복사

12

예제 입력 3 복사

8 8
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB

예제 출력 3 복사

0

예제 입력 4 복사

9 23
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBW

예제 출력 4 복사

31

예제 입력 5 복사

10 10
BBBBBBBBBB
BBWBWBWBWB
BWBWBWBWBB
BBWBWBWBWB
BWBWBWBWBB
BBWBWBWBWB
BWBWBWBWBB
BBWBWBWBWB
BWBWBWBWBB
BBBBBBBBBB

예제 출력 5 복사

0

예제 입력 6 복사

8 8
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBBBWBW
WBWBWBWB
BWBWBWBW
WBWBWWWB
BWBWBWBW

예제 출력 6 복사

2

예제 입력 7 복사

11 12
BWWBWWBWWBWW
BWWBWBBWWBWW
WBWWBWBBWWBW
BWWBWBBWWBWW
WBWWBWBBWWBW
BWWBWBBWWBWW
WBWWBWBBWWBW
BWWBWBWWWBWW
WBWWBWBBWWBW
BWWBWBBWWBWW
WBWWBWBBWWBW

예제 출력 7 복사

15

풀이

  • 검정색과 하얀색 두 가지 경우 밖에 없기 때문에 'B'일 경우 0, 'W'일 경우 1로 0과 1로 변경하여 2차원 배열을 입력받는다.
  • 맨 위쪽 칸의 색에 따라 색칠해야 하는 횟수가 바뀌기 때문에 두 경우 모두를 확인해야 한다.
  • 첫 번째 칸이 흰색일 경우 해당 위치의 인덱스(x, y)를 더한 값이 모두 짝수가 되고, 첫 번째 칸이 검은색일 경우 인덱스 를 더한 값이 홀수가 된다.

  • 만약 흰색이 들어갈 자리에 검정색이 들어가 있을 경우 횟수를 증가시키고 벡터에 값을 저장하고 가장 작은 수를 구해 출력하였다.
void CheckBoard(int n, int m)
{
	int _firstCount = 0;
	int _secondCount = 0;

	for (int i = n; i < n + 8; i++)
	{
		for (int j = m; j < m + 8; j++)
		{
			// 흰색 타일로 시작할 때
			if ((i + j) % 2 == board[i][j])
			{
				_firstCount++;
			}
			// 검정 타일로 시작할 때
			if ((i + j + 1) % 2 == board[i][j])
			{
				_secondCount++;
			}
		}
	}

	v.push_back(_firstCount);
	v.push_back(_secondCount);
}

코드

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

#define MAX 51

int N, M;   // 세로, 가로
int board[MAX][MAX];
vector<int> v;

// 흰색 자리에 검은색이 존재할 경우 색칠해야하는 횟수를 증가
// 체스판이 검은색으로 시작했을 때 or 흰색으로 시작했을 때 색칠해야하는 수를 구하여 벡터에 저장
void CheckBoard(int n, int m)
{
	int _firstCount = 0;
	int _secondCount = 0;

	for (int i = n; i < n + 8; i++)
	{
		for (int j = m; j < m + 8; j++)
		{
			// 흰색 타일로 시작할 때
			if ((i + j) % 2 == board[i][j])
			{
				_firstCount++;
			}
			// 검정 타일로 시작할 때
			if ((i + j + 1) % 2 == board[i][j])
			{
				_secondCount++;
			}
		}
	}

	v.push_back(_firstCount);
	v.push_back(_secondCount);
}


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

	// 세로 가로 입력
	cin >> N >> M;

	for (int i = 0; i < N; i++)
	{
		string str;
		cin >> str;
		for (int j = 0; j < M; j++)
		{
			// 검은색: 0, 하얀색 1로 변경하여 체스판 입력 받음
			if (str[j] == 'B')
				str[j] = 0;
			else
				str[j] = 1;
			board[i][j] = str[j];
		}
	}

	// 8*8 사이즈로 잘라 체스판 탐색
	for (int i = 0; i < N-7; i++)
	{
		for (int j = 0; j < M-7; j++)
		{
			CheckBoard(i, j);
		}
	}

	// 벡터에 담긴 수 중 가장 작은 값 반환하여 출력하기
	int answer = *min_element(v.begin(), v.end());
	cout << answer;

	return 0;
}

'C++ > Brute Force' 카테고리의 다른 글

[C++] 백준 7568 - 덩치  (1) 2022.12.16
[C++] 백준 2231 - 분해합  (0) 2022.12.16
[C++] 백준 2798 - 블랙잭  (1) 2022.12.12

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

 

2798번: 블랙잭

첫째 줄에 카드의 개수 N(3 ≤ N ≤ 100)과 M(10 ≤ M ≤ 300,000)이 주어진다. 둘째 줄에는 카드에 쓰여 있는 수가 주어지며, 이 값은 100,000을 넘지 않는 양의 정수이다. 합이 M을 넘지 않는 카드 3장

www.acmicpc.net

문제

카지노에서 제일 인기 있는 게임 블랙잭의 규칙은 상당히 쉽다. 카드의 합이 21을 넘지 않는 한도 내에서, 카드의 합을 최대한 크게 만드는 게임이다. 블랙잭은 카지노마다 다양한 규정이 있다.

한국 최고의 블랙잭 고수 김정인은 새로운 블랙잭 규칙을 만들어 상근, 창영이와 게임하려고 한다.

김정인 버전의 블랙잭에서 각 카드에는 양의 정수가 쓰여 있다. 그 다음, 딜러는 N장의 카드를 모두 숫자가 보이도록 바닥에 놓는다. 그런 후에 딜러는 숫자 M을 크게 외친다.

이제 플레이어는 제한된 시간 안에 N장의 카드 중에서 3장의 카드를 골라야 한다. 블랙잭 변형 게임이기 때문에, 플레이어가 고른 카드의 합은 M을 넘지 않으면서 M과 최대한 가깝게 만들어야 한다.

N장의 카드에 써져 있는 숫자가 주어졌을 때, M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 구해 출력하시오.

입력

첫째 줄에 카드의 개수 N(3 ≤ N ≤ 100)과 M(10 ≤ M ≤ 300,000)이 주어진다. 둘째 줄에는 카드에 쓰여 있는 수가 주어지며, 이 값은 100,000을 넘지 않는 양의 정수이다.

합이 M을 넘지 않는 카드 3장을 찾을 수 있는 경우만 입력으로 주어진다.

출력

첫째 줄에 M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 출력한다.

예제 입력 1 복사

5 21
5 6 7 8 9

예제 출력 1 복사

21

예제 입력 2 복사

10 500
93 181 245 214 315 36 185 138 216 295

예제 출력 2 복사

497

풀이

  • 두번째 줄에 주어진 숫자 중 3개를 더한 값이 M(딜러가 외친 숫자)과 같거나 가까운 값(but, M을 초과해서는 안 됨)을 출력해야 하는 문제이다.
  • 주어진 숫자를 배열에 저장하고, 3중 for문 이용하여 배열에 저장되어 있는 수 중 3개를 더한 값을 sum 변수에 저장한다. 이 중 M과 같거나 작을 경우,  max 함수를 사용해 가장 큰 값을 반환한다. (제일 큰 수는 M과 같은 수)

 

코드

#include <iostream>

using namespace std;

#define MAX 101

int N, M;
int sum;
int result = 0;

int blackJack[MAX];

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

	// 카드의 개수와 딜러가 외친 숫자 입력 받기
	cin >> N >> M;

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

	for (int i = 0; i < N; i++)
	{
		for (int j = i + 1; j < N; j++)
		{
			for (int k = j + 1; k < N; k++)
			{
				sum = blackJack[i] + blackJack[j] + blackJack[k];
				if (sum <= M)
				{
					result = max(result, sum);	// 둘 중 큰 값을 반환
				}
			}

		}
	}

	cout << result;
	return 0;
}

'C++ > Brute Force' 카테고리의 다른 글

[C++] 백준 7568 - 덩치  (1) 2022.12.16
[C++] 백준 2231 - 분해합  (0) 2022.12.16
[C++] 백준 1018 - 체스판 다시 칠하기  (0) 2022.12.16

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

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,

www.acmicpc.net

 

문제

철수의 토마토 농장에서는 토마토를 보관하는 큰 창고를 가지고 있다. 토마토는 아래의 그림과 같이 격자모양 상자의 칸에 하나씩 넣은 다음, 상자들을 수직으로 쌓아 올려서 창고에 보관한다.

창고에 보관되는 토마토들 중에는 잘 익은 것도 있지만, 아직 익지 않은 토마토들도 있을 수 있다. 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다. 하나의 토마토에 인접한 곳은 위, 아래, 왼쪽, 오른쪽, 앞, 뒤 여섯 방향에 있는 토마토를 의미한다. 대각선 방향에 있는 토마토들에게는 영향을 주지 못하며, 토마토가 혼자 저절로 익는 경우는 없다고 가정한다. 철수는 창고에 보관된 토마토들이 며칠이 지나면 다 익게 되는지 그 최소 일수를 알고 싶어 한다.

토마토를 창고에 보관하는 격자모양의 상자들의 크기와 익은 토마토들과 익지 않은 토마토들의 정보가 주어졌을 때, 며칠이 지나면 토마토들이 모두 익는지, 그 최소 일수를 구하는 프로그램을 작성하라. 단, 상자의 일부 칸에는 토마토가 들어있지 않을 수도 있다.

입력

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100, 1 ≤ H ≤ 100 이다. 둘째 줄부터는 가장 밑의 상자부터 가장 위의 상자까지에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 하나의 상자에 담긴 토마토의 정보가 주어진다. 각 줄에는 상자 가로줄에 들어있는 토마토들의 상태가 M개의 정수로 주어진다. 정수 1은 익은 토마토, 정수 0 은 익지 않은 토마토, 정수 -1은 토마토가 들어있지 않은 칸을 나타낸다. 이러한 N개의 줄이 H번 반복하여 주어진다.

토마토가 하나 이상 있는 경우만 입력으로 주어진다.

출력

여러분은 토마토가 모두 익을 때까지 최소 며칠이 걸리는지를 계산해서 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

예제 입력 1 복사

5 3 1
0 -1 0 0 0
-1 -1 0 1 1
0 0 0 1 1

예제 출력 1 복사

-1

예제 입력 2 복사

5 3 2
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0

예제 출력 2 복사

4

예제 입력 3 복사

4 3 2
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
-1 -1 -1 -1
1 1 1 -1

예제 출력 3 복사

0

코드

#include <iostream>
#include <queue>
#include <cstring>

using namespace std;

#define MAX 101

#define _X first.first	
#define _Y first.second
#define _Z second

int board[MAX][MAX][MAX];

int M, N, H;	// 가로, 세로, 높이
int temp = 0;
int day = 0;

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

queue<pair<pair<int, int>, int>> q;		// {{M, N}, H} 저장

void Bfs()
{
	while (!q.empty())
	{
		pair<pair<int, int>, int> cur = q.front();
		int x = cur._X;
		int y = cur._Y;
		int z = cur._Z;
		q.pop();

		for (int i = 0; i < 6; i++)
		{
			int nx = x + dx[i];
			int ny = y + dy[i];
			int nz = z + dz[i];

			// 범위를 벗어나거나, 토마토가 존재하지 않을 경우 무시
			if (nx < 0 || nx >= N || ny < 0 || ny >= M || nz < 0 || nz >= H) continue;
			if (board[nx][ny][nz] == -1) continue;

			// 익은 토마토 근처에 익지 않은 토마토가 존재할 경우 큐에 담고 
			if (board[nx][ny][nz] == 0)
			{
				q.push({ {nx, ny}, nz });
				board[nx][ny][nz] = board[x][y][z] + 1;
			}
		}
	}
}

// 현재 배열에 담긴 토마토의 상태를 확인한다.
// 배열에 0이 있을 경우에 익지 않은 토마토가 존재한다는 뜻이다.
// 그 외는 일수를 출력한다.
void CheckBoard()
{
	for (int h = 0; h < H; h++)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < M; j++)
			{
				// 만약 익지 않은 토마토가 존재할 경우 -1을 출력한다.
				if (board[i][j][h] == 0)
				{
					cout << -1;
					return;
				}

				// 현재 배열의 값 저장하여 최소 일수를 저장한 값과 비교
				// 만약 현재 배열 값(temp)가 크면 day에 값 덮어씌움
				temp = board[i][j][h];

				if (day < temp)
					day = temp;
			}
		}
	}
	// 익은 토마토가 1이기 때문에 일수를 구하기 위해서는 1을 빼줘야 한다.
	cout << day - 1;
}

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

	cin >> M >> N >> H;

	// 3차원 배열 입력
	for (int h = 0; h < H; h++)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < M; j++)
			{
				cin >> board[i][j][h];
			}
		}
	}

	// 익은 토마토가 있으면 해당 위치값을 큐에 저장한다.
	for (int h = 0; h < H; h++)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < M; j++)
			{
				if (board[i][j][h] == 1)
				{
					q.push({ { i, j }, h });
				}
				
			}
		}
	}

	Bfs();
	CheckBoard();

	return 0;
}

'C++ > BFS, DFS' 카테고리의 다른 글

[C++] 백준 2178 - 미로 탐색  (0) 2022.12.25
[C++] 백준 2606 - 바이러스  (0) 2022.12.25
[C++] 백준 7576 - 토마토  (0) 2022.12.11
[C++] 백준 5014 - 스타트 링크  (0) 2022.12.06
[c++] 백준 2468 - 안전 영역  (1) 2022.12.06

+ Recent posts