본문 바로가기
자료구조와 알고리즘/[Inflearn_큰돌] 10주 완성 C++ 코딩테스트

1주차-1. 2979번 트럭 주차, 카운팅 배열에 대한 개념

by 헛둘이 2022. 9. 12.

 

2979번 트럭 주차 문제

 

문제의 요지는 주차된 차량 별 3가지 요금을 입력 받아서,주차된 차량이 몇 대냐에 따라 1대 당 요금을 다르게 책정하고최종적으로 발생하는 비용을 물어보는 문제였다.

 

 

 

 

 

 

 

 


먼저 무작정 풀어보기

 

값을 입력 받고, for문의 범위를 정하기 위해 최대 / 최소를 구하는 로직

int A, B, C;
cin >> A >> B >> C;

int arr[3][2] = {};
int min = 101, max = -1;

for (int i = 0; i < 3; i++)
{
	for (int j = 0; j < 2; j++)
	{
		cin >> arr[i][j];
		if (arr[i][j] >= max)
			max = arr[i][j];
            

		if (arr[i][j] <= min)
			min = arr[i][j];
            
        // 아래 for문의 범위를 정하기 위해 max / min 값을 가져옴

	}
}
  • 범위를 정하기 위해 최소 / 최대 값을 가져왔다.

 

 

 

 

 

 

 

주차된 트럭 대수를 체크하고 주차비용을 계산하는 로직

	bool checkTruck[3] = { false, false, false };
   
	for (int i = min; i < max; i++)
	{

		if (i == arr[0][0])
			checkTruck[0] = true;

		if (i == arr[1][0])
			checkTruck[1] = true;

		if (i == arr[2][0])
			checkTruck[2] = true;

		if (i == arr[0][1])
			checkTruck[0] = false;

		if (i == arr[1][1])
			checkTruck[1] = false;

		if (i == arr[2][1])
			checkTruck[2] = false;
            
       		 // i번째 트럭이 오면 on
       		 // i번째 트럭이 떠나면 off 

		int sum = 0;
		// 그리고 총 몇 대가 주차되어 있는지 확인하고, 트럭 대수에 따라 sum에 누적
		switch (checkTruck[0] + checkTruck[1] + checkTruck[2])
		{
		case 0:
			break;

		case 1:
			sum += A;
			break;

		case 2:
			sum += 2 * B;
			break;

		case 3:
			sum += 3 * C;
			break;
		}
	}
  • 2차원 배열의 0번째 값에 도착 시간, 2차원 배열의 1번째 값에 떠난 시간을 넣어서 시간에 따라 계산될 수 있도록 했다.
  • bool 값을 이용해서 총 몇 대가 주차되었는지 확인하고 그 수에 따라 누적시켰다.

 

 

 

 

전체 코드

#include <iostream>

using namespace std;

int main()
{
	
	int A, B, C;
	cin >> A >> B >> C;

	int sum = 0;
	
	int arr[3][2] = {};
	int min = 101, max = -1;

	bool checkTruck[3] = { false, false, false };

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 2; j++)
		{
			cin >> arr[i][j];
			if (arr[i][j] >= max)
				max = arr[i][j];

			if (arr[i][j] <= min)
				min = arr[i][j];

		}
	}

	for (int i = min; i < max; i++)
	{

		if (i == arr[0][0])
			checkTruck[0] = true;

		if (i == arr[1][0])
			checkTruck[1] = true;

		if (i == arr[2][0])
			checkTruck[2] = true;

		if (i == arr[0][1])
			checkTruck[0] = false;

		if (i == arr[1][1])
			checkTruck[1] = false;

		if (i == arr[2][1])
			checkTruck[2] = false;


		switch (checkTruck[0] + checkTruck[1] + checkTruck[2])
		{
		case 0:
			break;

		case 1:
			sum += A;
			break;

		case 2:
			sum += 2 * B;
			break;

		case 3:
			sum += 3 * C;
			break;
		}
	}

	cout << sum << endl;
}

 

정답!...!?

  • 코드가 많이 길어지고 가독성이 떨어지긴 하지만 결국 풀렸다.
  • 하지만 분명 더 좋은 방법이 있을 것 같다..ㅎㅎ

 

 

 


카운팅 배열의 개념
  • 카운팅 배열은 특정한 규칙에 의해 구간마다 누적되는 값을 담아놓은 배열이라고 이해했다.
  • 예를 들어 트럭 예제의 경우를 예로 들면 1 6이라는 입력이 있고 3 5라는 입력이 있으면
  • 필요한 만큼의 0으로 초기화된 배열을 만들고, 처음에는 1 2 3 4 5번 인덱스에 1을 더해준다.(1 6 구간)
  • 그리고 3 5 입력에 대해서 3 4번 인덱스에 다시 1을 더해준다.
  • 이로써 3분 4분 구간에는 트럭이 2대 주차되어 있었다는 얘기가 된다.
  • 지나간 시간을 재는 경우 트럭이 동시에 있었다고 해서 그 시간을 계산하는 것을
  • 꼭 동시에 재야 하는게 아니라는걸 느끼게 됐다.
위에 내가 짠 코드의 문제점은 for문안에 모든 연산을 집어넣고 시간대마다 트럭이 몇 대인지
그 순간 순간에 다 측정하려는 내 성급함이 문제였던 것 같다.
1대가 먼저 와서 1시에서 6시까지 있었고~ 다시 다른 1대가 와서 3시부터 5시까지 있었으니~
이런 식으로 천천히 생각할 필요성을 느꼈다.

 

 

카운팅 배열로 다시 짠 코드
#include <iostream>

using namespace std;

int main()
{
	
	int A, B, C;
	cin >> A >> B >> C;

	int sum = 0;
	
	int arr[3][2] = {};
	int min = 101, max = -1;

	int countingArr[101] = {};

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 2; j++)
		{
			cin >> arr[i][j];
			if (arr[i][j] > max)
				max = arr[i][j];

			if (arr[i][j] < min)
				min = arr[i][j];
		}
	}

	// 카운팅 배열 만들기
	// 배열의 i번째 요소의 0번 = 도착 시간
	// 배열의 i번째 요소의 1번 = 떠난 시간
	for (int i = 0; i < 3; i++)
	{
		for (int j = arr[i][0]; j < arr[i][1]; j++)
		{
			countingArr[j]++;
		}
	}

	// 각 시간마다 몇 대 머물렀는지 확인하고 그 시간에 따른 비용 합산
	for (int i = min; i <= max; i++)
	{
		switch (countingArr[i])
		{
		case 1:
			sum += A;
			break;

		case 2:
			sum += B * 2;
			break;

		case 3:
			sum += C * 3;
			break;
		}
	}

	cout << sum << endl;
}
  • 잘 작동했고, 라인 수도 훨씬 줄어들었고 코드 자체도 간결해진 느낌이 있다.

 

  • 메모리는 동일했지만 코드 길이에서 차이가 난다.

댓글