문제 출처 : https://www.acmicpc.net/problem/11723
문제
비어있는 공집합 S가 주어졌을 때, 아래 연산을 수행하는 프로그램을 작성하시오.
- add x: S에 x를 추가한다. (1 ≤ x ≤ 20) S에 x가 이미 있는 경우에는 연산을 무시한다.
- remove x: S에서 x를 제거한다. (1 ≤ x ≤ 20) S에 x가 없는 경우에는 연산을 무시한다.
- check x: S에 x가 있으면 1을, 없으면 0을 출력한다. (1 ≤ x ≤ 20)
- toggle x: S에 x가 있으면 x를 제거하고, 없으면 x를 추가한다. (1 ≤ x ≤ 20)
- all: S를 {1, 2, ..., 20} 으로 바꾼다.
- empty: S를 공집합으로 바꾼다.
입력
첫째 줄에 수행해야 하는 연산의 수 M (1 ≤ M ≤ 3,000,000)이 주어진다.
둘째 줄부터 M개의 줄에 수행해야 하는 연산이 한 줄에 하나씩 주어진다.
출력
check 연산이 주어질때마다, 결과를 출력한다.
메모리 제한
- Java 8: 448 MB
- Java 8 (OpenJDK): 448 MB
- Java 11: 448 MB
- Kotlin (JVM): 448 MB
- C# 9.0 (.NET): 64 MB
- Java 15: 448 MB
- F# (.NET): 64 MB
- Visual Basic (.NET): 64 MB
풀이
간단한 구현 문제이다.
문제에서 요구하는 함수들을 구현하는 것은 어렵지 않다.
다만 입력이 크기 때문에 아무 생각 없이 풀면 시간 초과가 뜰 것이다.
코드 1과 코드 2의 차이를 보면, wirte를 쓰냐, print를 쓰냐의 차이로 통과, 시간 초과가 나뉘었다.
즉, 그냥 생각나는 대로 함수 구현해서 풀면 되는데, 빠른 입출력을 사용해야 한다.
c++같은 경우 cout <<endl 대신, cout<<'\n'을 사용하고, ios::sync_with_stdio(false), cin.tie,cout.tie 등의 방법이 있다.
알고리즘 분류를 보면 비트마스킹이 있는데, 위에서 말한 대로 그냥 빠른 입출력 쓰고 함수 일반적으로 구현하면 통과한다.
본인은 비트마스킹 복습할 때 풀려고 아껴두고 있다ㅎㅎ
비트마스킹 공부중!
아래 코드3이 비트마스킹 풀이이다.
입력받은 num은 1 << (num -1)을 해준다.
num이 만약 3이라면 1 << (3-1)로 0b100이 되는 것이다.
all 함수는 (1 << 21) -1 -> 0b11111111111111111111 로 구현하고,
add, toggle는 or, xor로 쉽게 구현할 수 있다.
remove는 and를 써야 하는데 S = S and num을 하면 S에 0 혹은 num이 남기 때문에 not연산자를 이용했다.
코드1
import java.util.*
val br = System.`in`.bufferedReader()
var arr = IntArray(21)
fun add(num : Int){
arr[num]=1
}
fun remove(num : Int){
arr[num]=0
}
fun check(num : Int) :Int{
return arr[num]
}
fun toggle(num : Int){
arr[num] = arr[num] xor 1
}
fun all(){
arr = IntArray(21){1}
}
fun empty(){
arr = IntArray(21)
}
fun main() =with(System.out.bufferedWriter()){
val n = br.readLine().toInt()
for(i in 0 until n) {
val tk = StringTokenizer(br.readLine())
val input = Array<String>(2){""}
var idx=0
while(tk.hasMoreTokens()){
input[idx++]=tk.nextToken()
}
when {
input[0] == "add" -> add(input[1].toInt())
input[0] == "remove" -> remove(input[1].toInt())
input[0] == "check" -> write("${ check(input[1].toInt())}\n")
input[0] == "toggle" -> toggle(input[1].toInt())
input[0] == "all" -> all()
else -> empty()
}
}
close()
}
코드2 (시간 초과)
import java.util.*
val br = System.`in`.bufferedReader()
var arr = IntArray(21)
fun add(num : Int){
arr[num]=1
}
fun remove(num : Int){
arr[num]=0
}
fun check(num : Int){
println(arr[num])
}
fun toggle(num : Int){
arr[num] = arr[num] xor 1
}
fun all(){
arr = IntArray(21){1}
}
fun empty(){
arr = IntArray(21)
}
fun main() =with(System.out.bufferedWriter()){
val n = br.readLine().toInt()
for(i in 0 until n) {
val tk = StringTokenizer(br.readLine())
val input = Array<String>(2){""}
var idx=0
while(tk.hasMoreTokens()){
input[idx++]=tk.nextToken()
}
when {
input[0] == "add" -> add(input[1].toInt())
input[0] == "remove" -> remove(input[1].toInt())
input[0] == "check" -> check(input[1].toInt())
input[0] == "toggle" -> toggle(input[1].toInt())
input[0] == "all" -> all()
else -> empty()
}
}
close()
}
코드3 (비트마스킹)
import java.util.*
val br = System.`in`.bufferedReader()
fun main() = with(System.out.bufferedWriter()){
val m = br.readLine().toInt()
var S = 0
for(i in 0 until m){
val tk = StringTokenizer(br.readLine())
val order = tk.nextToken()
val num = if(order=="all" || order=="empty") 0 else 1 shl (tk.nextToken().toInt() -1)
when{
order == "all" ->{
S = (1 shl 21) -1
}
order == "empty" ->{
S = 0
}
order == "add" ->{
S = S or num
}
order =="remove" ->{
S = (S and num).inv() and S
}
order =="toggle" ->{
S = S xor num
}
else ->{
if(S and num == num){
write("1\n")
}
else{
write("0\n")
}
}
}
}
close()
}
'알고리즘 문제 풀이 > 백준' 카테고리의 다른 글
백준 12094 2048 (Hard) Kotlin (시뮬레이션, 백트래킹) (0) | 2021.12.23 |
---|---|
백준 12100 2048 (Easy) Kotlin (시뮬레이션) (0) | 2021.12.23 |
백준 18870 좌표 압축 Kotlin (정렬) (0) | 2021.12.23 |
백준 11559 Puyo Puyo Kotlin (시뮬레이션) (0) | 2021.12.22 |
백준 2644 촌수계산 Kotlin (dfs,bfs) (0) | 2021.12.22 |
댓글