Problem Solving

알고리즘 :: 백준 :: 2852 - NBA 농구

soreDemo 2025. 1. 8. 00:00

문제

🔗문제링크

🔄 문제 및 입출력 조건 파악

  • 득점 개수 1 ≤ N ≤ 100
  • 각 득점 정보는 문자열로 "mm:ss" 형식
  • 출력: 1번팀이 이기고 있던 시간, 2번팀이 이기고 있던 시간

✏️ 문제풀이

1. 시간(초)을 하나의 칸으로 생각하는 방법

'분'과 '초' 서로 다른 단위가 있을 때는 어느 한 쪽 단위로, 되도록이면 작은 단위로 통일하는 것이 좋습니다.

농구경기 48분을 초로 환산하면 2,880초이므로 전체 농구경기를 연속된 2,880칸으로 표현할 수 있습니다.

 

문자열 "mm:ss"가 주어졌을 때, `int` 타입의 초로 환산하는 방법은 다음과 같습니다.

60 * stoi(line.substr(0, 2)) + stoi(line.substr(3));

 

예제 입력 2를 예시로 과정을 설명해보겠습니다.

  • A팀이 01:10에 골을 넣었다고 가정합시다.
    초로 환산하면 70입니다. 70부터 2,880까지 모든 배열 값을 +1 해줍니다.
  • B팀이 21:10에 골을 넣었다고 가정합시다.
    초로 환산하면 1,270입니다. 1,270부터 2,880까지 모든 배열 값을 -1 해줍니다.
  • B팀이 31:30에 골을 넣었다고 가정합시다.
    초로 환산하면 1,890입니다. 1,890부터 2,880까지 모든 배열 값을 -1 해줍니다.
  • 모든 배열을 탐색하며 양수(+)값을 가진다면 A팀이 이기고 있던 순간,
    음수(-)값을 가진다면 B팀이 이기고 있던 순간
    입니다.
  • 이렇게 시간을 구했다면, 답을 출력할 때는 반대로 다시 문자열로 바꿔줘야 합니다.
    • 0은 "00"으로, 1~9는 "01"~"09"로 바꿔줘야 합니다.
    • `to_string(이기고 있던 시간 / 60)`의 길이가 1이라면 "0"을 하나 덧붙여줘야 합니다.

2. 이전 시간을 기록하며 진행하는 방법

매 루프마다 이전 시간을 `past` 라는 문자열에 저장할 겁니다.

이번 루프에 득점 팀과 시간을 입력받았을 때,

  • A팀이 이기고 있는 상태였다면, A팀이 이기고있던 시간에 현재시간 - `past`를 기록해줍니다.
  • B팀이 이기고 있는 상태였다면, B팀이 이기고있던 시간에 현재시간 - `past`를 기록해줍니다.
  • 방금 막 입력받은 득점 팀은 다음 루프에 반영됩니다.
    • 득점을 A팀이 넣었다면 A팀 점수++,
    • B팀이 넣었다면 B팀 점수++ 해줍니다.

방법 1 보다는 덜 직관적이라 조금 햇갈릴 수 있지만, 한 번만 예제를 따라서 진행하면 바로 이해할 수 있습니다.

📝 코드

1. 시간(초)을 하나의 칸으로 생각하는 방법

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

inline void printResult(int t) {
	string mm = to_string(t / 60);
	if (mm.length() == 1) mm = "0"s + mm;
	string ss = to_string(t % 60);
	if (ss.length() == 1) ss = "0"s + ss;
	cout << mm << ":" << ss << '\n';
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int N;
	cin >> N;
	array<int, 2880> t = {0, };
	while (N--) {
		int team;
		string line;
		cin >> team >> line;
		
		int mm = stoi(line.substr(0, 2));
		int ss = stoi(line.substr(3, 2));
		for (int i = 60 * mm + ss; i < 2880; ++i)
			(team == 1) ? t[i]++ : t[i]--;
	}
	int time_a = 0, time_b = 0;
	for (int i = 0; i < 2880; ++i) {
		if (t[i] > 0) time_a++;
		else if (t[i] < 0) time_b++;
	}
	printResult(time_a);
	printResult(time_b);
}

🔗 코드 링크

2. 이전 시간을 기록해가는 방법

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

inline int convStrToSec(const string& str) {
	return (60 * stoi(str.substr(0, 2)) + stoi(str.substr(3)));
}

inline void printResult(int t) {
	string mm = to_string(t / 60);
	if (mm.length() == 1) mm = "0"s + mm;
	string ss = to_string(t % 60);
	if (ss.length() == 1) ss = "0"s + ss;
	cout << mm << ":" << ss << '\n';
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	
	int N;
	cin >> N;
	
	int A = 0, B = 0, timeA = 0, timeB = 0;
	string past;
	
	while (N--) {
		int team;
		string now;
		cin >> team >> now;
		
		if (A > B) timeA += (convStrToSec(now) - convStrToSec(past));
		else if (B > A) timeB += (convStrToSec(now) - convStrToSec(past));
		
		team == 1 ? A++ : B++;
		past = now;
	}
	if (A > B) timeA += (convStrToSec("48:00"s) - convStrToSec(past));
	else if (B > A) timeB += (convStrToSec("48:00"s) - convStrToSec(past));
	
	printResult(timeA);
	printResult(timeB);
}

🔗 코드 링크

🕧 결과