https://www.acmicpc.net/problem/9375

 

9375번: 패션왕 신해빈

첫 번째 테스트 케이스는 headgear에 해당하는 의상이 hat, turban이며 eyewear에 해당하는 의상이 sunglasses이므로   (hat), (turban), (sunglasses), (hat,sunglasses), (turban,sunglasses)로 총 5가지 이다.

www.acmicpc.net

코드설명

HashMap + 경우의 수에 대한 이해 문제입니다.

 

처음에 풀었을떄는 각 경우에 대한 조합을 만들었습니다.

즉, 1개로 이루어진 조합, 2개로 이루어진 조합, 3개로 이루어진 조합 ... 을 만든뒤에

각 경우에서 만들어질 수 있는 경우의 수를 모두 더했습니다.

 

하지만 시간초과가 발생합니다. 

먼저 왜 시간초과가 발생하는지 알아봅니다.

테스트케이스 T는 100입니다.

해빈이가 가진 의상의 수는 최대 30개입니다. 

 

현재 시간복잡도는,

입력처리에는 O(TN).

조합계산에는 O(2^N) 입니다.(선택할지 말지 2가지 경우의 수를 N번 반복합니다.)

N = 30 이므로 2^30(1073741824) 이므로, 문제에서 주어진 1초 안에는 미세한 차이로 불가합니다.

 

더 좋은 방식이 있습니다.

문제에서는 "옷을 입지 않는 경우"를 구해야만 합니다.

그렇다면, 옷을 입지 않는 경우 1개를 각 옷의 종류에 한개씩 추가합니다.

그리고 마지막에 옷을 입지 않는 경우가 모든 옷의 종류에서 선택되는 경우인 1 가지를 뺴주면됩니다.

 

이렇게 문제를 풀 수 있는 방법을 생각해야한다는점에서 좋은 문제인 것 같습니다.

코드

package algorhythm;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.StringTokenizer;
public class Main {
public static int N, C, T;
public static HashMap<String, Integer> hashmap = new HashMap<>();
public static int answer = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
T = Integer.parseInt(st.nextToken());
while(T-- > 0) {
hashmap = new HashMap<>();
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
String a = st.nextToken();
String b = st.nextToken();
hashmap.put(b, hashmap.getOrDefault(b, 0) + 1);
}
answer = 1;
//만약 들어온 옷의 종류가 1개라면, 각각의 개수만 더해집니다.
for(Entry<String, Integer> entrySet : hashmap.entrySet()) {
answer *= (entrySet.getValue() + 1);
}
answer -= 1;
System.out.println(answer);
}
}
}
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
public class Main {
public static int N, T, M;
public static int answer = 0;
public static int[] cache;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
T = Integer.parseInt(st.nextToken());
cache = new int[11];
Arrays.fill(cache, -1);
while(T-- > 0) {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
HashMap<String, Integer> hashmap = new HashMap<>();
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
String clothName = st.nextToken();
String clothKind = st.nextToken();
hashmap.put(clothKind, hashmap.getOrDefault(clothKind, 0) + 1);
}
answer = 1;
for(Map.Entry<String, Integer> entrySet : hashmap.entrySet()){
answer = answer * (entrySet.getValue() + 1);
}
answer -= 1;
System.out.println(answer);
}
}
}

 

모든 조합마다의 각 시간을 모두 연산합니다. 시간복잡도(2^N)

그렇기에, 시간초과가 나는 코드입니다.

package algorhythm;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.StringTokenizer;
public class Main {
public static int N, C, T;
public static HashMap<String, Integer> hashmap = new HashMap<>();
public static StringBuilder sb = new StringBuilder();
public static int answer = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
T = Integer.parseInt(st.nextToken());
while(T-- > 0) {
hashmap = new HashMap<>();
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
String a = st.nextToken();
String b = st.nextToken();
hashmap.put(b, hashmap.getOrDefault(b, 0) + 1);
}
answer = 0;
int size = hashmap.keySet().size();
int[] value = new int[size];
int index = 0;
//만약 들어온 옷의 종류가 1개라면, 각각의 개수만 더해집니다.
for(Entry<String, Integer> entrySet : hashmap.entrySet()) {
value[index++] = entrySet.getValue();
}
for(int i=1; i<=size;i++) {
//combination (1), combination(2) .. 가 실행됨.
//그러면 1 일때 3. 2일때 2개. 로 5가 나와야함.
combination(0, 0, i, value, new int[i]);
}
sb.append(answer);
}
System.out.println(sb.toString());
}
public static void combination(int level, int idx, int maxSize, int[] value, int[] selected) {
if(level == maxSize) {
//원하는 숫자만큼 정해졌다면, 해당 내에서 나올 수 있는 개수를 구합니다.
int temp = 1;
for(int i=0;i<selected.length;i++) {
temp *= value[selected[i]];
}
answer += temp;
return ;
}
for(int i=idx;i<value.length;i++) {
selected[level] = i;
combination(level + 1, i + 1, maxSize, value, selected);
selected[level] = -1;
}
}
}

   

+ Recent posts