728x90
패션왕 신해빈
다국어
시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
1 초 | 128 MB | 25199 | 13765 | 11810 | 54.810% |
문제
해빈이는 패션에 매우 민감해서 한번 입었던 옷들의 조합을 절대 다시 입지 않는다. 예를 들어 오늘 해빈이가 안경, 코트, 상의, 신발을 입었다면, 다음날은 바지를 추가로 입거나 안경대신 렌즈를 착용하거나 해야한다. 해빈이가 가진 의상들이 주어졌을때 과연 해빈이는 알몸이 아닌 상태로 며칠동안 밖에 돌아다닐 수 있을까?
입력
첫째 줄에 테스트 케이스가 주어진다. 테스트 케이스는 최대 100이다.
- 각 테스트 케이스의 첫째 줄에는 해빈이가 가진 의상의 수 n(0 ≤ n ≤ 30)이 주어진다.
- 다음 n개에는 해빈이가 가진 의상의 이름과 의상의 종류가 공백으로 구분되어 주어진다. 같은 종류의 의상은 하나만 입을 수 있다.
모든 문자열은 1이상 20이하의 알파벳 소문자로 이루어져있으며 같은 이름을 가진 의상은 존재하지 않는다.
출력
각 테스트 케이스에 대해 해빈이가 알몸이 아닌 상태로 의상을 입을 수 있는 경우를 출력하시오.
예제 입력 1 복사
2
3
hat headgear
sunglasses eyewear
turban headgear
3
mask face
sunglasses face
makeup face
예제 출력 1 복사
5
3
힌트
첫 번째 테스트 케이스는 headgear에 해당하는 의상이 hat, turban이며 eyewear에 해당하는 의상이 sunglasses이므로 (hat), (turban), (sunglasses), (hat,sunglasses), (turban,sunglasses)로 총 5가지 이다.
흐름
내가 짠 로직은 도저히 1초 내로 수행될 것 같지 않으므로 (테스트 케이스 반복문까지 포함하면 for문 3개이상..) 강의를 봤다.
선생님 logic (파란색)
안입는 경우를 포함하여 경우의 수를 구한다면,
3C1(종류 하나만 입었을때), 3C2(종류 2개 입었을때), 3C3(종류 3개 입었을때)를 각각 구하여 더하지않고
안입은 경우를 포함한 종류 개수를 3번 곱한 것 - 1(아무것도 입지않았을때) = 답이 된다.
이 로직으로 코드를 작성했다.
코드
#include <bits/stdc++.h>
using namespace std;
int tc, n, ret=1;
string s1, s2;
map<string, int> m;
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
//1. 문제 입력받기
cin >> tc; //테스트 케이스 수
for(int i=0;i<tc;i++){
cin >> n; //의상 수
//2. 종류마다 의상 수 저장
for(int j=0;j<n;j++){
cin >> s1 >> s2;
m[s2]++;
}
//3. 총 경우의 수 구하기 (안입었을때를 포함, +1)
for(auto it=m.begin();it != m.end();it++){
ret *= (it-> second +1);
}
//4. 답 출력 (모두 안입었을때를 제외, -1)
cout << ret-1 << "\n";
// 값 초기화(테스트케이스가 여러개이므로)
m.clear(); //맵 원소 모두 삭제
ret=1;
}
}
맞았다.
유의할 점
- map은 쌍으로 저장하므로 value값은 *it이 아닌 it->second이다. (iterator는 주소값)
it < m.end()가 아닌 it != m.end() 이다. (iterator는 주소값을 반환하고, end는 마지막 원소의 바로 뒤, 쓸모없는 값을 가리킨다.)- 한 줄에 공백이 있는 두 단어가 주어질때, cin.getline도 좋지만 cin >> s1 >> s2로 받으면 split 하지않고 바로 사용 가능하다.
선생님 코드
#include <bits/stdc++.h>
using namespace std;
int t, n;
string a, b;
int main(){
//1. 입력 받기
cin >> t;
while (t--){
map<string, int> _map;
cin >> n;
//2. 종류마다 1씩 저장하기
for(int i=0;i<n;i++){
cin >> a >> b;
_map[b]++;
}
//3. 경우의 수 구하기
long long ret=1;
for(auto c:_map){
ret *= ((long long) c.second +1);
}
ret--;
//4. 출력
cout << ret << "\n";
}
return 0;
}
포인트
- 테스트 케이스마다 반복할 경우 global 변수는 상태값이 저장되므로 지역변수를 사용하자.
- map은 하나씩 확장되어 추가되므로 지역변수에서 초기값을 굳이 지정안해도 된다.(배열의 초기화와 다름)
- map, set이 이진 탐색 트리로 구성되어있음과 관련된 것 같다.
- 곱한 결과를 저장하는 ret 변수는 long long 타입으로 지정하는 것이 좋다.(오버플로우 방지)
- iterator인 m.begin(), m.end() 사용할 필요 없이 pair 원소 접근하여 for (auto c : m) { cout << c.second; }로 바로 사용가능하다. (auto로 맵 원소를 접근할 경우 iterator가 아닌 !! pair원소를 가리킨다. )
- https://yonmy.com/archives/9 <= 대충 insert시에는 pair을 리턴하므로 ret.first->second="haha"로 원소를 수정하든 접근하자고 하는 내용
- 테스트케이스가 여러개 존재할 경우 while문 사용하는 것이 편하다. while(t--)
728x90
'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글
1940번: 주몽 [C++] (0) | 2023.01.04 |
---|---|
1213번: 팰린드롬 만들기 [C++] (0) | 2023.01.04 |
1620번: 나는야 포켓몬 마스터 이다솜 [C++] (2) | 2023.01.03 |
2559번 : 수열 [C++] (2) | 2023.01.03 |
9996번: 한국이 그리울 땐 서버에 접속하지 (0) | 2022.12.31 |