포스트

SWEA 2001 | 파리 퇴치

SWEA 2001번 파리 퇴치 풀이

SWEA 2001 | 파리 퇴치

Problem 💻

N x N 배열 안의 숫자는 해당 영역에 존재하는 파리의 개수를 의미한다.

아래는 N=5 의 예이다.

2001_01.png

M x M 크기의 파리채를 한 번 내리쳐 최대한 많은 파리를 죽이고자 한다.

죽은 파리의 개수를 구하라!

예를 들어 M=2 일 경우 위 예제의 정답은 49마리가 된다.

2001_02.png

[제약 사항]

  1. N 은 5 이상 15 이하이다.

  2. M은 2 이상 N 이하이다.

  3. 각 영역의 파리 갯수는 30 이하 이다.

[입력]

가장 첫 줄에는 테스트 케이스의 개수 T가 주어지고, 그 아래로 각 테스트 케이스가 주어진다.

각 테스트 케이스의 첫 번째 줄에 N 과 M 이 주어지고,

다음 N 줄에 걸쳐 N x N 배열이 주어진다.

[출력]

출력의 각 줄은 ‘#t’로 시작하고, 공백을 한 칸 둔 다음 정답을 출력한다.

(t는 테스트 케이스의 번호를 의미하며 1부터 시작한다.)

입력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
10
5 2
1 3 3 6 7
8 13 9 12 8
4 16 11 12 6
2 4 1 23 2
9 13 4 7 3
6 3
29 21 26 9 5 8
21 19 8 0 21 19
9 24 2 11 4 24
19 29 1 0 21 19
10 29 6 18 4 3
29 11 15 3 3 29
...

출력

1
2
3
#1 49
#2 159
...

Approach 1 ❌

  • 완전 탐색(브루트포스) 방식으로 접근하였다.
  • 문제 해결에는 문제없었지만 N이 커지면 문제가 생길 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...		
		int max = -1;
		for (int i = 0; i <= N - M; ++i)
		{
			for (int j = 0; j <= N - M; ++j)
			{
				int numFly = 0;
				for (int k = 0; k < M; ++k)
				{
					for (int m = 0; m < M; ++m)
					{
						numFly += fly[i + k][j + m];
					}
				}
				
				if (max < numFly)
				{
					max = numFly;
				}
			}
		}
...

Approach 2 ⭕

  • 브루트포스가 아닌 누적 합을 이용하여 풀이하는 방식으로 수정하였다.
  • 이와 유사한 문제를 다음에 만나면 브루트포스를 생각하기 보다는 누적 합 방식을 한번 고려해봐야 겠다.

Solution 💡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<iostream>
#include<vector>

using namespace std;

int main(int argc, char** argv)
{
	int test_case;
	int T;

	cin >> T;

	for (test_case = 1; test_case <= T; ++test_case)
	{
		int N, M;

		cin >> N >> M;

		vector<vector<int>> fly(N, vector<int>(N));
		vector<vector<int>> prefixSum(N + 1, vector<int>(N + 1, 0));
		for (int i = 0; i < N; ++i)
		{
			for (int j = 0; j < N; ++j)
			{
				cin >> fly[i][j];
				prefixSum[i + 1][j + 1] = fly[i][j] + prefixSum[i][j + 1] + prefixSum[i + 1][j] - prefixSum[i][j];

			}
		}

		int max = -1;
		for (int i = M; i <= N; ++i)
		{
			for (int j = M; j <= N; ++j)
			{
				if (prefixSum[i][j] + prefixSum[i - M][j - M] - prefixSum[i - M][j] - prefixSum[i][j - M] > max)
				{
					max = prefixSum[i][j] + prefixSum[i - M][j - M] - prefixSum[i - M][j] - prefixSum[i][j - M];
				}
			}
		}

		cout << "#" << test_case << ' ' << max << '\n';
	}
	return 0;//정상종료시 반드시 0을 리턴해야합니다.
}

Reference 📄

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PzOCKAigDFAUq

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.