코딩 테스트/알고리즘 풀이

[백준 - 17509] And the Winner Is... Ourselves!

김띠띵 2022. 9. 1. 22:50

||문제 이해

각 문제들의 최소 패널티 총합을 구하는 문제

 

각 문제는 D(풀이 시간), V(오답판정 개수) 가 있다.

풀이 시간 : 시간은 누적된다!

각 문제의 패널티는 D + (20 * V) 로 구해진다.


||해결 계획

처음은 마땅히 좋은 방법이 생각안나서 시간이 작은것 부터 해볼까라는 생각으로 무작정 시작했다.

이 처럼 같은 전략의 반복은 Greedy가 어울려 Greedy를 사용한다.


||계획 검증

두가지 경우가 있다.

시간의 비교, 오답판정의 비교

어떤 경우를 먼저 해야 하는지 검증해본다.

시간의 비교

두개의 문제가 있다 생각한다.

1번 : D = 10, V = 1

2번 : D = 20, V = 1

 

시간이 작은것부터 할 경우

1. 10 + 20 = 30

2. 30 + 20 = 50

= 30 + 50 = 80

 

시간이 큰것부터 할 경우

1. 20 + 20 = 40

2. 30 + 20 = 50

= 40 + 50 = 90

 

즉, 시간은 작은것부터 해야 최소가 나온다.

오답판정의 비교

두개의 문제가 있다 생각한다.

1번 : D = 10, V = 1

2번 : D = 10, V = 2

 

오답판정이 작은것부터 할 경우

1. 10 + 20 = 30

2. 20 + 40 = 60

= 30 + 60 = 90

 

오답판정이 큰것부터 할 경우

1. 10 + 40 = 50

2. 20 + 20 = 40

= 50 + 40 = 90

 

즉, 오답 판정은 상관 없다.

 

그럼 시간을 오름차순으로 정렬만 해주고 계산해주면 정답이 나온다.


||구현

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

typedef pair<int, int> pii;
#define Time first
#define Verdict second

//시간을 오름차순으로 정렬
bool comp(const pii & a, const pii & b)
{
	return a.Time < b.Time;
}

pii p[MAX];
int main()
{
	ios::sync_with_stdio(0), cin.tie(0);

	for (int i = 0; i < MAX; ++i)
	{
		cin >> p[i].Time >> p[i].Verdict;
	}
	sort(p, p + MAX, comp);

	int result = 0;
	int time = 0;
	for (auto data : p)
	{
		time += data.Time;
		result += time + (data.Verdict * 20);
	}

	cout << result;
	return 0;
}

||되돌아 보기

일단 숨겨진 조건을 찾기 어려웠다ㅠ (영어라 내가 해석을 잘 못해서 그런걸 수도 있다...)

그 조건은 시간이 누적된다는 점이다.

 

처음에는 어 그냥 각 문제마다 D + 20 * V 하면 되는거 아니야? 하고 테스트 케이스를 보고 비교했지만

어림도 없었다.

 

그러다 생각나게 시험이니까 시간이 누적된 시간으로 계산 하는 것인가? 하고 테스트케이스와 비교해서 알아냈다.

영어도 공부 많이 해야겠다..ㅜ