[BAEKJOON - C++] 11098 : 첼시를 도와줘!

정다은·2023년 7월 2일
0

BAEKJOON

목록 보기
2/54
C++ 배우기 (51~100) 이 문제집을 참고하여 문제를 풀었습니다.

2023년 1월에서 2월에 프로그래밍을 공부하기 위해 풀었던 문제들이다.

🍑문제

구단이 성적을 내지 못한다면 답은 새 선수 영입뿐이다. 이것은 오늘날 유럽 리그에서 가장 흔한 전략이고, 노르웨이의 로젠버그 팀은 이러한 전략이 성공한 대표적 예시다. 그들은 많은 스카우터들을 지구 곳곳에 파견해 가능성 있는 루키를 찾는다.
현재 첼시는 프리미어 리그에서 헤매고 있고, 결국 새로운 선수를 사기로 결정했다. 하지만 그들은 스카우터를 기다리기 지쳤고, 훨씬 더 효율적인 전략을 개발해냈다. "만약 무언가 팔리고 있다면, 그것에는 합당한 이유가 있다"는 배룸의 명언이 바로 그것이다. 축구에서 이 말은 곧 가장 비싼 선수가 가장 좋은 선수라는 이야기가 된다.
이에 따라 새로운 선수를 찾는 방법은 단순히 구단들에게 전화를 걸어 그들의 가장 비싼 선수를 사는게 되었다. 당신의 임무는 첼시가 리스트에서 가장 비싼 선수를 찾아낼 수 있도록 돕는 것이다.

입력
첫 번째 줄에는 테스트 케이스의 개수 n이 주어진다 (n≤100).
각 테스트 케이스의 첫 번째 줄 p는 고려해야될 선수의 수이다 (1≤p≤100).
그 아래 p개의 줄에는 선수의 정보가 표시된다.
각각의 줄은 선수의 가격 C 와 이름을 입력한다 (C<2*109).
모든 선수의 가격은 서로 다르다.
선수의 이름은 20자 이하여야 하며, 사이에 공백이 있어서는 안 된다.

출력
각각의 테스트 케이스에서 가장 비싼 선수의 이름을 출력해야한다.

🍑대략적인 틀

  • 첫번째 시도 알고리즘 메모
    • 첫째줄에 테스트가 돌아갈 횟수를 입력받음
      • 정수형 변수 testNum
    • 두번째줄에 테스트에 응할 선수수가 입력됨
    • 테스트가 여러번 진행된다면 시행을 시작할 때 마다 선수수 입력
      • 정수형 변수 personNum
    • 그 뒤로 ' 선수가격 이름 ' 이렇게 입력 받음
    • 테스트가 여러번 진행된다면 시행을 시작할 때 마다 선수가격과 이름 입력
    • while문을 써서 testNum이 0이 되지 않는 동안 전체 test가 진행되도록함. test 한번 시행하고 나서 testNum--; 가 실행 되게 함.
    • 선수가격과 이름을 어떻게 분리하여 저장할지가 문제이긴한데, 시험해보니 숫자도 string에 들어간다. 그러면 getline으로 받고 공백으로 분리하면 될듯하다.
    • isdigit 함수로 숫자가 끝나는 인덱스를 찾고 substr 로 분리하면 되려나? 공백을 기준으로 문자열을 분리하는것이 너무나 어렵다 ㅜㅜ
      1. 문자열 입력을 char 형식의 배열로 받고 strtok 사용
      2. findex를 이용하여 공백의 인덱스를 알아내어 분리
      3. 애초에 받을 때 구별해서 받기! 알아서 띄어쓰기로 분리해 저장함
    • 각 리스트에서(test 한번당 나오는 선수 목록) 가장 비싼 선수를 출력한다.
      • 그러면 가장 비싼 선수를 저장해야한다.
    • 근데 1977에서 부터 드는 의문이지만 cin을 연달아 써야할때 한줄로 연결하는 방법은 없을까?

첫 시도는 몇시간동안 했음에도 실패 했기에 나는 알고리즘부터 코드까지 다 엎고 다시하기로 했다

  • 첫째줄에 테스트의 개수 입력 받음(100이하)
  • 각 테스트마다 고려해야 할 선수 수 입력 받음(1~100)
  • 선수의 수만큼 고려해야할 선수의 정보를 입력 받음(선수이름, 가격)

🍑오류 해결

  1. 자꾸 abort() has been called 오류가 떠서 찾아보니 프로그램이 thread가 종료되기전에 종료 되버려서 생기는 오류라고 한다. 첫번째 입력까지는 괜찮은데 두번째 입력 부터는 통 말썽이어서 너무 어지러웠다. 그래서 문자열이 하나여서 배열에 받을 필요가 없는 경우로 코드를 시험해보니 코드 자체는 잘 작동이 되었다. 아무래도 배열에서 충돌을 일으킨것 같았다.
  • 수정하여 시험해본 코드
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main() {
    	string list = " ";
    	int price;
    	string name;
    	getline(cin, list);
    	int Index = list.find(" ", 0);
    	price = stoi(list.substr(0, Index));
    	name = list.substr(Index + 1);
    
    	cout << price << " " << name;
    }

계속하여 stoi 가 문제를 일으켜서 결국에는 stoi를 쓰지 않고 문자열을 받고 분리하는게 아니라 애초부터 분리해서 받기로 했다. 그 간단한 것을 생각 못했던 것이다. 그냥 cin 으로 띄어쓰기를 기준으로 연달아 받았으면 되는 일인데 말이다.

  1. 두번째로 막혔던 문제는 가장 비싼 것으로 판단된 선수의 출력이다. while문이 돌아가면서 반복되므로 마지막에 한꺼번에 출력을 하려면 배열에 저장한 후에 출력해야하는데 그 string 배열에 저장하여 출력하는 것이 굉장히 애매했다. 결국 성공했는데… vs 에서는 되는데 백준에서는 runtime error segfault ㅜㅜ

그리고 내가 스스로 코드를 짜면서도 내 코드가 너무 더럽고 얽혀있어서 나중에 좀 시간이 지나고 나면 꼭 다시 깔끔한 코드로 작성해보리라 다짐했다.

결국엔 맞은 코드가 가장 깔끔하게 되었다. 마지막에 주르륵 출력하지 않아도 된다는 것을 알아서 그런것도 있고 6일 사이에 코드를 구현하는 실력이 조금이나마 는게 아닐까 하고 기대해본다 😆

그리고 첼시 두번째 시도에서도 실수 했던건데 배열을 사용할 때 인덱스를 변수 + 정수 꼴로 만드는 것은 괜찮지만 변수 - 정수 꼴로 만들면 변수가 0일때, 또한 음수일때를 대비하여 내가 실제로 1이상의 정수만 넣는다고 해도 미리 오버플로우를 방지한다고 오류가 난다는 것을 알았다.

🍑 작성한 코드

// 첼시를 도와줘!

#include <iostream>
#include <string>
using namespace std;

int main() {
	int test, max, index;
	cin >> test;

	int* price;
	string* name;

	while (true) {
		int num;
		cin >> num;

		price = new int[num];
		name = new string[num];
		max = -1;
		for (int i = 0; i < num; i++) {
			cin >> price[i] >> name[i];
			if (price[i] > max) {
				max = price[i];
				index = i;
			}
		}
		cout << name[index] << '\n';

		delete[]price, num;
		test--;
		if (test == 0)
			break;
	}
}
profile
보안 공부하는 대학교 3학년 / 시리즈에서 더욱 편하게 글을 찾아보실 수 있습니다:)

0개의 댓글