당신은 주제를 찾고 있습니까 “비트 마스크 – [DANCE] MVSK – Kep1er (케플러) | Dance Cover Practice“? 다음 카테고리의 웹사이트 ppa.maxfit.vn 에서 귀하의 모든 질문에 답변해 드립니다: https://ppa.maxfit.vn/blog. 바로 아래에서 답을 찾을 수 있습니다. 작성자 쏘하_Ssoha 이(가) 작성한 기사에는 조회수 98,125회 및 좋아요 4,352개 개의 좋아요가 있습니다.
비트 마스크 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 [DANCE] MVSK – Kep1er (케플러) | Dance Cover Practice – 비트 마스크 주제에 대한 세부정보를 참조하세요
최근에 올라온 [방구석여기서요?] MVSK 커버 연습영상이에요!
멤버들 다 열심히 연습했는데 촬영할 때 다들 너무 오랜만에 추느라 쪼오금 아쉬워서
완벽한 연습 영상은 아니지만 올려봅니당 👀
너무너무 오랜만에 업로드하죠? 😅
이제 가끔이라도 업로드 해보려고 노력해보겠슴둥,,,💕
#MVSK #Kep1er #댄스커버
비트 마스크 주제에 대한 자세한 내용은 여기를 참조하세요.
비트마스크(BitMask) 는 무엇인가? :: 마이구미
이 글은 비트마스크(BitMask) 기법에 대해 다룬다. 특정 알고리즘이 아닌, bit 를 활용한 테크닉이라고 할 수 있다. bit 는 low level 이 아닌 경우 …
Source: mygumi.tistory.com
Date Published: 4/20/2021
View: 6858
비트마스크 (BitMask) 알고리즘 – Rebro의 코딩 일기장
– 비트마스크(BitMask)는 이진수를 사용하는 컴퓨터의 연산 방식을 이용하여, 정수의 이진수 표현을 자료 구조로 쓰는 기법을 말한다. – 이진수는 0 또는 …
Source: rebro.kr
Date Published: 12/9/2022
View: 2889
비트마스크(BitMask) | Tech Interview – Gyoogle
# 왜 비트마스크를 사용하는가? · DP나 순열 등, 배열 활용만으로 해결할 수 없는 문제 · 작은 메모리와 빠른 수행시간으로 해결이 가능 (But, 원소의 수가 …
Source: gyoogle.dev
Date Published: 2/20/2022
View: 5892
[Algorithms] 비트 마스크 (Bitmask) |
[Algorithms] 비트 마스크 (Bitmask) · 1. 이점. 빠른 연산속도; 메모리 효율적; 배열을 정수로 대체하므로 index로 활용 가능 · 2. 비트 연산. 기본; 자주 …
Source: jooncco.com
Date Published: 7/27/2022
View: 2961
[알고리즘] 비트마스킹(bitmasking) 이란 – 굳건하게
컴퓨터는 내부적으로 모든 자료를 이진수로 표현합니다. 이와 같은 특성을 이용해 정수의 이진수 표현을 자료구조로 쓰는 기법을 비트 마스크라고 합니다.
Source: travelbeeee.tistory.com
Date Published: 2/23/2022
View: 73
비트마스크(bitmask)란 무엇인가? – JustKode
거두절미 하고 이야기 하면, 비트마스크는 알고리즘 이라기 보단 테크닉에 가깝습니다. 비트는 컴퓨터에서 다루는 최소 단위이며, 정수를 이진수로 …
Source: justkode.kr
Date Published: 9/29/2021
View: 1928
비트 마스크 (Bit Mask) – 코딩 맛집
비트 마스크(Bit Mask) 기법은 말 그대로 비트(Bit)를 마스킹하는 기술 입니다. 비트를 마스킹 한다는 것은 &(AND 연산자), | (OR 연산자) 등의 비트 …
Source: coding-food-court.tistory.com
Date Published: 9/1/2021
View: 9218
[알고리즘] 비트(Bit)와 비트마스크(BitMask) 정리 (Java)
toBinaryString() 메서드는 단지 비트연산자가 컴퓨터 내부에서 어떻게 처리되는지 문자열로 표현해주기 위해 사용했다. 결과값. 비트마스크 (bit mask).
Source: loosie.tistory.com
Date Published: 4/4/2021
View: 2239
비트마스킹(BitMasking) 이 뭐야? – velog
최근에 카카오에서는 비트마스크 문제를 좋아한다고 해서, 비트마스킹이 뭐지라는 생각에 해당 분야를 살펴봤다.오랫만에 논리연산자를 다시 공부하게 …
Source: velog.io
Date Published: 9/28/2022
View: 6338
[알고리즘 개념] 비트마스크(Bitmask) – 계범 개발일지
이진수(Bit)를 이용하는 기법. 비트마스크를 사용하는 이유. 빠른 수행시간; 작은 메모리 사용량; 간결한 코드. bit연산을 사용하기때문에 …
Source: cano721.tistory.com
Date Published: 10/26/2021
View: 9879
주제와 관련된 이미지 비트 마스크
주제와 관련된 더 많은 사진을 참조하십시오 [DANCE] MVSK – Kep1er (케플러) | Dance Cover Practice. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 비트 마스크
- Author: 쏘하_Ssoha
- Views: 조회수 98,125회
- Likes: 좋아요 4,352개
- Date Published: 2022. 4. 16.
- Video Url link: https://www.youtube.com/watch?v=OF1T16YFexY
비트마스크(BitMask) 는 무엇인가? :: 마이구미
반응형
이 글은 비트마스크(BitMask) 기법에 대해 다룬다.
특정 알고리즘이 아닌, bit 를 활용한 테크닉이라고 할 수 있다.
bit 는 low level 이 아닌 경우에는 크게 비트를 다룰 일은 없어보이지만, 분명 이해가 필요한 경우는 드물지 않다.
그렇기에, 프로그래밍 문제 풀이가 아니더라도 많은 도움이 될 것이다.
대략적인 설명이후에, 백준 알고리즘 2098번 “외판원 순회” 을 풀이한다.
백준 알고리즘 2098번 문제 “외판원 순회” – https://www.acmicpc.net/problem/2098
비트마스크는 무엇인가?
용어 그대로 비트(Bit) 에 관련된 것이다.
비트는 이진 숫자(binary digit) 를 뜻하는 말로 컴퓨터에서 사용되는 데이터의 최소 단위이다.
비트는 0, 1 의 값을 가질 수 있고, true/false 또는 on/off 라는 상태를 나타낸다.
이건 흔히 알고 있는 지식으로 컴퓨터는 0, 1 두가지 숫자만으로 표현하는 이진법을 사용하는 것을 의미한다.
* 일반적으로 우리가 다루는 표현 방식이 0 ~ 9 숫자를 사용하는 10진법이다.
위처럼 이진수 1101 은 우리가 아는 숫자 13로 표현될 수 있다.
비트마스크는 무엇인가?
비트마스크는 이러한 비트의 형태를 활용한다.
알고리즘보다는 테크닉 중 하나로써, 정수의 이진수 표현을 활용한 기법이다.
여기까지 비트를 통해 알 수 있는 2가지 정보는 다음과 같다.
이진수는 0, 1 만을 가지고, true/fasle 상태를 가진다.
이진수는 십진수로 표현 가능하다.
그렇다면 과연 이를 어떻게 활용할 수 있을까?
우리는 길이가 5인 집합 { 0, 1, 2, 3, 4 } 가 존재한다고 가정해본다.
여기서 몇가지 요소를 뽑아 어떤 요소를 선택했는 지 표현할 수 있다.
즉, 집합의 어떤 요소를 구성하고 있는지를 나타내는 부분집합을 어떻게 표현할 수 있는가?
{ 1, 2, 3, 4 }, { 1, 2, 4 }, { 2, 4 }, { 1 } ………..
위와 같은 형태로, Integer 형으로 인덱스를 활용할 수 있다면, 단순히 boolean 배열을 통해 구현할 수도 있다.
int[] array1 = [1, 1, 1, 1, 0]; int[] array2 = [1, 1, 0, 1, 0]; int[] array3 = [1, 0, 1, 0, 0];
하지만 이건 많은 메모리를 차지하고 오버헤드가 증가한다.
비트마스크를 통해 더욱 효율적이게 할 수 있다.
{ 0, 1, 2, 3, 4 } => 11111
{ 1, 2, 3, 4 } => 11110
{ 1, 2, 4 } => 10110
{ 2, 4 } => 10100
{ 1 } => 00010
각 요소는 인덱스처럼 표현할 수 있다.
즉, 집합 i 번째 요소가 부분집합에 존재한다면 1 을 의미하고, 그렇지 않으면 0 을 의미한다.
그리고 위에서 언급했었던, 2진수를 10진수로 표현할 수도 있다.
{ 0, 1, 2, 3, 4 } => 11111 => (2^4 * 1) + (2^3 * 1) + (2^2 * 1) + (2^1 * 1) + (2^0 * 1) = 31
{ 1, 2, 3, 4 } => 11110 => (2^4 * 1) + (2^3 * 1) + (2^2 * 1) + (2^1 * 1) = 30
{ 1, 2, 4 } => 10110 => (2^4 * 1) + (2^2 * 1) + (2^1 * 1) = 22
{ 2, 4 } => 10100 => (2^4 * 1) + (2^2 * 1) = 20
{ 1 } => 00010 => (2^1 * 1) = 2
부분집합을 배열이 아닌 정수를 통해 나타낼 수 있게 된다.
즉, 20 이란 정수는 부분집합 { 2, 4 } 를 나타내는 것을 의미한다.
{ 2, 4 } 부분집합에서 i를 추가하고 싶으면, 단순히 i번째 비트의 값을 1로 변경해주면 된다.
이러한 삽입, 삭제, 조회와 같은 행위는 비트 연산을 통해 쉽게 제어할 수 있다.
제어를 위해 비트 연산에 대해 간략히 설명한다.
AND, OR, XOR, NOT, SHIFT 가 존재한다.
AND 연산(&)
대응하는 두 비트가 모두 1일 때, 1을 반환.
1010 & 1111 = 1010
OR 연산(|)
대응하는 두 비트가 모두 1 또는 하나라도 1일 때, 1을 반환.
1010 | 1111 = 1111
XOR 연산(^)
대응하는 두 비트가 서로 다르면 1을 반환.
1010 | 1111 = 0101
NOT 연산(~)
비트의 값을 반전하여 반환.
~1010 = 0101
시프트(Shift) 연산(>>, <<) 왼쪽 또는 오른쪽으로 비트를 옮긴다. 00001010 << 2 = 101000 00001010 >> 2 = 000010
왼쪽 시프트는 A * 2^B 를 의미하고, 오른쪽 시프트는 A / 2^B 를 의미한다.
0001 -> 0010 -> 0100 -> 1000 => 1, 2, 4, 8 …..
1000 -> 0100 -> 0010 -> 0001 => 8, 4, 2, 1 …..
(A + B) / 2 를 (A + B) >> 1 로 사용할 수도 있듯이 많은 곳에서 일반적인 사칙연산을 더 효율적으로 할 수 있다.
기본적인 비트 연산을 연습할 수 있는 문제를 통해 해보는 것도 나쁘지 않다. (https://www.acmicpc.net/problem/12813)
비트 연산자를 사용해도 되지만, 이론적으로 구현하면 다음과 같다.
// A&B for (int i = 0; i < len; i++) { c[i] = a[i] == 1 && b[i] == 1 ? 1 : 0; } // A|B for (int i = 0; i < len; i++) { c[i] = a[i] == 1 || b[i] == 1 ? 1 : 0; } // A^B for (int i = 0; i < len; i++) { c[i] = a[i] != b[i] ? 1 : 0; } // ~A for (int i = 0; i < len; i++) { c[i] = a[i] == 1 ? 0 : 1; } // ~B for (int i = 0; i < len; i++) { c[i] = b[i] == 1 ? 0 : 1; } 이제 어떻게 비트 연산을 통해 삽입, 삭제, 조회를 할 수 있는가? 1010 로 표현하고 있을 때, i번째 비트의 값을 1로 어떻게 변경할 수 있을까? i = 2 이라고 가정할 때, 결과는 1110 을 원한다. 2번째 비트를 1로 변경할 수 있는 방법은 다음과 같다. 1010 | 1 << 2 1010 | 0100 => 1110
시프트 연산을 통해 2번째 비트만 1로 할당되어 있는 이진수를 만든다.
그리고 OR 연산을 통해 원하는 결과를 만들 수 있다.
반대로 2 번째 비트의 값을 0로 어떻게 변경할 수 있을까?
1110 & ~1 << 2 1110 & 1011 => 1010
AND 연산과 NOT 연산을 활용할 수 있다.
그리고 i번째 비트의 값을 알 수 있는 방법은 다음과 같다.
A & (1 << i) 2번째 비트 - 1010 & (1 << 2) = 1010 & 0100 => 0
3번째 비트 – 1010 & (1 << 3) = 1010 & 1000 => 1000
AND 연산과 시프트 연산을 통해 i번째 비트의 값이 0이라면 값이 0이라는 것을 알 수 있다.
이렇게 비트를 활용한 테크닉을 통해 접근하는 것이 비트마스크인 것이다.
마지막으로 문제를 통해 비트마스크를 활용한 예를 보자.
비트마스크를 대표 문제라고도 볼 수 있는 “외판원 순회”이다.
이 문제의 풀이는 사실상 동적계획법(DP)에 비트마스크를 접목한 방식이다.
외판원 순회 문제는 영어로 Traveling Salesman problem (TSP) 라고 불리는 문제로 computer science 분야에서 가장 중요하게 취급되는 문제 중 하나이다. 여러 가지 변종 문제가 있으나, 여기서는 가장 일반적인 형태의 문제를 살펴보자.
1번부터 N번까지 번호가 매겨져 있는 도시들이 있고, 도시들 사이에는 길이 있다. (길이 없을 수도 있다) 이제 한 외판원이 어느 한 도시에서 출발해 N개의 도시를 모두 거쳐 다시 원래의 도시로 돌아오는 순회 여행 경로를 계획하려고 한다. 단, 한 번 갔던 도시로는 다시 갈 수 없다. (맨 마지막에 여행을 출발했던 도시로 돌아오는 것은 예외) 이런 여행 경로는 여러 가지가 있을 수 있는데, 가장 적은 비용을 들이는 여행 계획을 세우고자 한다.
각 도시간에 이동하는데 드는 비용은 행렬 W[i][j]형태로 주어진다. W[i][j]는 도시 i에서 도시 j로 가기 위한 비용을 나타낸다. 비용은 대칭적이지 않다. 즉, W[i][j] 는 W[j][i]와 다를 수 있다. 모든 도시간의 비용은 양의 정수이다. W[i][i]는 항상 0이다. 경우에 따라서 도시 i에서 도시 j로 갈 수 없는 경우도 있으며 이럴 경우 W[i][j]=0이라고 하자.
N과 비용 행렬이 주어졌을 때, 가장 적은 비용을 들이는 외판원의 순회 여행 경로를 구하는 프로그램을 작성하시오.
모든 도시를 한번만 방문하면서 다시 시작점으로 돌아오는 최소 거리 비용을 구하는 문제이다.
이 문제는 완전탐색 문제로써, 단순하게 풀면 경우의 수가 N! 로 시간초과를 경험하게 된다.
시간을 줄이기 위해 동적계획법으로 접근하고, 점화식은 다음과 같다.
dp[current][visited] = min(dp[current][visited], tsp(next, visited + next) + w[current][next])
현재 도시가 current 이고, 방문한 도시들의 집합이 visited 일 때, 나머지 도시들을 순회한 최소 비용이다.
여기서 visited 를 배열로 관리하는 것이 어렵기에, 비트마스크를 활용하는 것이다.
도시이 0~3번 까지 존재할 경우, 0번, 3번 도시를 들렸다는 것은 1001 로 표현할 수 있고, 정수로는 9를 의미한다.
즉, 2번 도시에서 0번, 3번을 방문하고 순회했을 때의 최소 비용은 dp[2][9] 를 의미하는 것이다.
점화식 이해를 위해 그림으로 조금 설명을 덧붙인다.
위처럼 dp[3][00001111] 에 모든 도시를 순회한 최소 비용이 구했다고 가정한다.
그렇다면, dp[3][00001111] 에 해당되는 것들은 나머지 도시들을 방문하지 않고, 이 최소 비용을 재사용하면 된다.
여기서 dp[3][00001111] 가 해당하는 경로는 다음과 같다.
0 -> 1 -> 2 -> 3 -> …….
0 -> 2 -> 1 -> 3 -> …….
0 -> 3 -> 1 -> 2 -> …….
0 -> 3 -> 2 -> 1 -> …….
위와 같은 부분적으로 문제를 나누어 해결한 모습을 볼 수 있다.
여기서는 사용되는 비트 연산은 다음과 같다.
모든 도시를 방문한 경우. (모든 비트의 값이 1 인지 판단)
이미 방문한 도시 여부. (i번째 비트의 값이 1 인지 판단)
다음 도시를 방문했을 경우. (i번째 비트의 값을 1로 변경)
자세한 건 전체 코드를 참고하길 바란다.
비트마스크 자체는 어려울 게 없으나, 다른 알고리즘 함께 사용되어 어렵게 느껴질 수 있다.
제약이 있지만, 여러모로 유용하게 쓸 수 있는 테크닉이라고 볼 수 있다.
백준 2098번 외판원 순회 전체 코드 – https://github.com/hotehrud/acmicpc/blob/master/algorithm/bitmask/2098.java
반응형
비트마스크 (BitMask) 알고리즘
728×90
반응형
[목차]1. 비트마스크(BitMask)란?
2. 비트마스크의 장점
3. 비트 연산자
4. 비트마스크를 이용한 집합 구현
* 종만북에 잘 설명되어 있어 기본적으로 종만북의 설명을 따릅니다.
1. 비트마스크(BitMask)란?
– 비트마스크(BitMask)는 이진수를 사용하는 컴퓨터의 연산 방식을 이용하여, 정수의 이진수 표현을 자료 구조로 쓰는 기법을 말한다.
– 이진수는 0 또는 1을 이용하므로 하나의 비트(bit)가 표현할 수 있는 경우는 두 가지이다.
– 보통 어떤 비트가 1이면 ” 켜져 있다”라고 말하며, 0이면 ” 꺼져 있다”라고 말한다.
2. 비트마스크의 장점
비트마스크는 크게 어려운 개념이 아니며, 이 개념을 알고 있다면 매우 유용한 경우가 꽤나 있다. 비트마스크의 장점들은 다음과 같다.
1. 수행 시간이 빠르다.
비트마스크 연산은 bit 연산이기 때문에 O(1)에 구현되는 것이 많다. 따라서 다른 자료구조를 이용하는 것보다 훨씬 빠르게 동작하게 된다.
다만, 비트마스크를 이용하는 경우에는 비트의 개수만큼 원소를 다룰 수 있기 때문에 연산 횟수가 적은 경우에는 속도에 큰 차이가 없지만, 연산 횟수가 늘어날수록 차이가 매우 커지게 된다.
2. 코드가 짧다.
다양한 집합 연산들을 비트연산자로 한 줄로 작성할 수 있기 때문에 반복문, 조건문 등을 이용한 코드보다 훨씬 간결한 코드를 작성할 수 있다.
3. 메모리 사용량이 더 적다.
개인적으로, 비트마스크를 이용하는 가장 큰 이유 라고 생각한다.
간단한 예시로, bit가 10개인 경우에는 각 bit당 두 가지 경우를 가지기 때문에 $2^{10}$가지의 경우를 10bit 이진수 하나로 표현이 가능하다.
이처럼 하나의 정수로 매우 많은 경우의 수를 표현할 수 있기 때문에 메모리 측면에서 효율적이며, 더 많은 데이터를 미리 계산해서 저장해 둘 수 있는 장점이 있다. (DP에 매우 유용하다)
3. 비트 연산자
비트마스크를 이용하기 위해서, 정수 변수를 비트 별로 조작할 수 있는 비트연산자를 사용한다. 두 정수 변수 또는 하나의 정수 변수를 이용하여 새로운 값을 만들어 내는 것이 목적이다.
1. AND 연산
두 정수 변수 a와 b를 통해서 c를 생성한다고 가정하면, a와 b를 한 bit씩 비교하면서 해당 비트가 둘 다 켜져 있는 경우에만 c의 해당 비트를 켠다.
C에서 제공하는 연산자 기호는 ‘ & ‘이다.
(ex. c = a & b)
2. OR 연산
AND 연산과 같은 방식으로, 해당 비트가 둘 중 하나라도 켜져 있는 경우에 c의 해당 비트를 켠다.
C에서 제공하는 연산자 기호는 ‘ | (shift + \) ‘ 이다.
(ex. c = a | b)
3. XOR 연산
마찬가지로 같은 방식이며, 해당 비트가 둘 중 하나만 켜져 있는 경우에 c의 해당 비트를 켠다.
C에서 제공하는 연산자 기호는 ‘ ^ ‘ 이다.
(ex. c = a ^ b)
4. NOT 연산
정수 하나를 입력받아서 켜져 있는 비트는 끄고, 꺼져 있는 비트는 켠 결과를 반환한다.
C에서 제공하는 연산자 기호는 ‘ ~ ‘ 이다.
(ex. c = ~a)
5. 시프트(shift) 연산
시프트 연산자는 정수 a의 비트들을 왼쪽 또는 오른쪽으로 원하는 만큼 움직인다. 움직이고 나서 빈자리는 0으로 채워지게 된다. 예를 들어 13 (1101)을 오른쪽으로 1bit 움직인다고 하면, 6 (0110)이 되는 것이다.
C에서 제공하는 연산자 기호는 ‘ << ' 또는 ' >> ‘ 이다.
(ex. c = (a << 1) ) 아래는 실제 예시이다. 단, 비트 연산자를 이용할 때에는 주의해야 할 점이 있다. 첫 번째로, C에서 비트 연산자들의 우선순위는 비교 연산자보다 낮다. 따라서 원하는 답이 나오지 않을 가능성이 있다. 예를 들어서 c = (6 & 4 == 4) 라고 한다면, 4 == 4가 먼저 계산되어 1(true)을 반환하고, 따라서 c에는 6 & 1의 값이 할당되게 된다. 따라서 비트 연산자를 이용할 때에는 항상 연산자마다 괄호를 씌워주는 것이 바람직하다. 두 번째로는, 오버플로우(Overflow) 문제이다. $ 2^{50} $ 을 구하기 위해서 1<<50 으로 표현한다면, C에서는 1은 32bit 상수 취급하기 때문에 50번 왼쪽으로 shift하게 되면 overflow가 발생하게 된다. 따라서 1LL로 표현을 해주어야 한다. 이처럼 비트 연산자를 사용하는 경우엔 실수할 가능성이 매우 높기 때문에 주의해서 사용해야 한다. 4. 비트마스크를 이용한 집합 구현 비트마스크를 이용한 집합 구현은 가장 대표적이고, 중요한 사례이다. " 하나의 bit가 하나의 원소 "를 의미하게 된다. bit가 켜져 있으면 해당 원소가 집합에 포함되어 있다는 의미이고, 꺼져 있으면 포함되어 있지 않다는 의미이다. 따라서 N비트 정수 변수라면 N개의 원소를 갖는 집합의 부분집합들을 모두 표현할 수 있게 된다. 원래는 N개의 boolean 원소를 갖는 배열을 선언해야 했지만, 비트마스크를 이용하면 정수 하나로 표현이 가능하기 때문에 사용하는 메모리의 크기가 많이 줄어드는 장점이 있다. 이제 비트연산자를 통해서 집합을 어떻게 효율적으로 다룰 수 있는지 알아보자. 우선, A라는 변수를 집합이라고 가정하고, 집합의 총원소의 개수를 10개라고 가정하겠다. (0번째 ~ 9번째 원소) 연산 사용 예시 공집합과 꽉 찬 집합 구하기 A = 0; / A = (1 << 10) - 1; 원소 추가 A |= (1 << k); 원소 삭제 A &= ~(1 << k); 원소의 포함 여부 확인 if(A & (1 << k)) 원소의 토글(toggle) A ^= (1 << k); 두 집합에 대해서 연산 A | B → A와 B의 합집합 A & B → A와 B의 교집합 A & (~B) → A에서 B를 뺀 차집합 A ^ B → A와 B중 하나에만 포함된 원소들의 집합 집합의 크기 구하기 int bitCount(int A){ if(A == 0) return 0; return A%2 + bitCount(A / 2); } [내장 명령어] gcc/g++ → __builtin_popcount(A) visual C++ → __popcnt(A) Java → Integer.bitCount(A) 최소 원소 찾기 int first = A & (-A); 최소 원소 지우기 A &= (A - 1); 모든 부분 집합 순회하기 for (int subset = A ; subset ; subset = ((subset - 1) & A)){ } 1) 공집합과 꽉 찬 집합 구하기 - 기본적으로 공집합은 bit가 모두 꺼진 상황이기 때문에 상수 0이 공집합을 표현한다. 반대로 꽉 찬 집합은 bit가 모두 켜진 상황이기 때문에 1111111111(2) 의 값을 가져야 하는데, 이는 (1<<10) - 1 과 동일하다. 1<<10은 10000000000(2) 이므로 1을 빼면 10개의 bit가 모두 켜진 수를 얻을 수 있다. 2) 원소 추가 - A 집합에 특정 원소를 추가하는 방법이다. 원소에 해당하는 bit만 켜야 하기 때문에 해당 bit를 항상 1로 만드는 연산이 필요하다. 따라서 OR 연산을 이용한다. 이미 A에 원소가 포함되어 있는 경우에는 아무런 변화가 없게 된다. 3) 원소 삭제 - A 집합에 포함된 특정 원소를 삭제하는 방법이다. 원소에 해당하는 bit가 꺼져야 하기 때문에 해당 bit를 항상 0으로 만드는 연산이 필요하다. 따라서 A -= (1<
👨🏻💻 Tech Interview
우리가 흔히 사용하는 10진수를 2진수로 바꾸면?
9(10진수) → 1001(2진수)
[1, 2, 3, 4 ,5] 라는 집합이 있다고 가정해보자.여기서 임의로 몇 개를 골라 뽑아서 확인을 해야하는 상황이 주어졌다. (즉, 부분집합을 의미)
물론, 간단히 for문 돌려가며 배열에 저장하며 경우의 수를 구할 순 있다.
하지만 비트마스킹을 하면, 각 요소를 인덱스처럼 표현하여 효율적인 접근이 가능하다.
집합의 i번째 요소가 존재하면 1 , 그렇지 않으면 0 을 의미하는 것이다.
이러한 2진수는 다시 10진수로 변환도 가능하다.
11111 은 10진수로 31이므로, 부분집합을 정수를 통해 나타내는 것이 가능하다는 것을 알 수 있다.
이로써, 해당 부분집합에 i를 추가하고 싶을때 i번째 비트를 1로만 바꿔주면 표현이 가능해졌다.
이런 행위는 비트 연산을 통해 제어가 가능하다.
비트연산 연습문제 : 백준 12813 (opens new window)
[Algorithms] 비트 마스크 (Bitmask)
if ( pizza & ( 1 << hamIdx )) { cout << "My pizza has ham on it !! " ; // good } if (( pizza & ( 1 << hamIdx )) == 1 ) { cout << "naa.. " ; // bad. & 연산의 결과값은 1이 아니다. }
[알고리즘] 비트마스킹(bitmasking) 이란
안녕하세요, 여행벌입니다.
오늘은 2진수 표기법의 특징을 활용한 비트마스킹 알고리즘에 대해서 포스팅해보겠습니다.
[ 비트마스킹 ]컴퓨터는 내부적으로 모든 자료를 이진수로 표현합니다. 이와 같은 특성을 이용해 정수의 이진수 표현을 자료구조로 쓰는 기법을 비트 마스크라고 합니다.
비트 마스크를 이용하면 더 빠른 수행 시간, 더 간결한 코드, 더 적은 메모리 사용이라는 효과를 얻을 수 있습니다.
비트 연산자
비트마스킹은 기본적으로 비트를 다뤄야 하므로, 비트 연산자에 대해서 먼저 간단하게 알아보겠습니다.
a & b a의 모든 비트와 b의 모든 비트를 AND연산한다.
둘다 1이라면 1, 아니면 0 ex)
a = 4 = 100(2)
b = 7 = 111(2)
a & b = 100(2) = 4 a | b a의 모든 비트와 b의 모든 비트를 OR연산한다.
둘다 0이라면 0, 아니면 1 ex)
a = 2 = 010(2)
b = 5 = 101(2)
a | b = 111(2) = 7 a ^ b a의 모든 비트와 b의 모든 비트를 XOR연산한다. 둘이 다르다면 1, 아니면 0 ex)
a = 3 = 011(2)
b = 5 = 101(2)
a ^ b = 110(2) = 6 ~a a의 모든 비트에 NOT 연산을 한다.
0이면 1, 1이면 0 ex) 3비트라고 가정
a = 3 = 011(2)
~a = 100(2) = 4 a << b a를 b비트 만큼 왼쪽으로 시프트 ex) a = 1 = 001(2) a << 2 = 100(2) = 4 a >> b a를 b비트 만큼 오른쪽으로 시프트 ex)
a = 4 = 100(2)
a >> 2 = 001(2) = 1
집합의 표현
비트마스크를 이용하면 집합을 쉽게 표현할 수 있습니다. 또, 집합에 원소를 추가, 삭제하는 등 다양한 연산을 굉장히 빠르게 수행할 수 있습니다.
그럼 비트를 이용해서 어떻게 집합을 표현할 수 있을까요? 원소의 개수가 N인 집합이 있다고 하면, 각각의 원소를 0번부터 (N-1)번 까지 번호를 부여하고, 번호에 해당하는 비트가 1이면 원소가 포함, 0이면 원소가 불포함이라고 한다면 집합을 비트를 이용해 표현할 수 있습니다.
예를 들어, { A, B, C, D, E, F, G } 집합이 있다고 하겠습니다.
총 7개의 원소가 존재하므로 우리는 7개의 비트로 이 집합을 표현할 수 있습니다. 즉, 각 원소마다 비트를 하나씩 대응시켜서 원소가 존재한다면 1, 존재하지 않다면 0으로 표현해보겠습니다.
예를 들어, { A } 라는 부분집합은 64 = 1000000(2) 로 표현하고 { C, F } 는 18 = 0010010(2) 로 표현할 것입니다.
원소 추가
현재 상태 cur이 있을 때, p번 원소를 추가한다고 해보겠습니다. 그럼, 현재 상태 cur에서 p번 비트를 1로 바꿔줘야 됩니다. a | b 비트연산자를 활용하면 쉽게 해결할 수 있습니다.
cur = cur | (1 << p) 1 << p를 통해서 p번 비트만 1, 나머지 비트는 0인 값을 만들고 | 연산을 진행한다면 cur의 p번 비트는 1로 바뀌게 되고, 나머지 비트는 원래 상태를 유지하게 됩니다. 원소 삭제 원소를 삭제하는 연산도 쉽게 구현할 수 있습니다. 현재 상태 cur에서 p번 원소를 삭제한다고 생각해보겠습니다. 그러면, p번 비트를 0으로 바꿔줘야됩니다. cur = cur & ~(1 << p); 1 << p 를 통해서 p번 비트만 1, 나머지 비트는 0으로 만듭니다. 그 후, ~ 연산을 통해 p번 비트만 0, 나머지 비트는 1로 만들고 & 연산을 진행한다면 p번 비트만 0으로 바뀌고 나머지는 현재 상태 cur과 동일하게 유지할 수 있습니다. 원소 토글 p번 비트가 1이면 0, 0이면 1로 바꾸는 토글 연산도 쉽게 구현할 수 있습니다. 현재 상태 cur에서 p번 원소가 있다면 삭제하고, 없다면 추가해보겠습니다. cur = cur ^ (1 << p); 1 << p 를 통해서 p번 비트만 1, 나머지 비트는 0으로 만듭니다. cur의 나머지 비트들은 0과 XOR 연산을 진행하므로 0이면 0, 1이면 1로 현재 상태를 유지하게 되고, p번 비트는 1과 XOR 연산을 진행하므로 1이면 0, 0이면 1로 토글이 됩니다. 집합 연산(합집합) 비트마스킹을 이용하면 원소를 추가, 삭제, 토글 하는 연산 외에도 합집합, 교집합, 차집합 등등을 쉽게 구할 수 있습니다. a | b; // a 와 b의 합집합 a & b; // a 와 b의 교집합 a & ~b; // a 에서 b를 뺀 차집합 a ^ b; // a와 b 중 하나에만 포함된 원소들의 집합 A집합을 나타내는 a와 B집합을 나타내는 b가 있을 때, 둘이 | 연산을 하게 된다면 존재하는 원소들의 비트는 모두 1로 켜지게 되고, 두 집합에 모두 없는 원소들만 비트가 0이 됩니다. 따라서, 합집합 연산이 됩니다. 마찬가지로 & 연산을 하게 되면, 두 집합에 모두 존재하는 원소들의 비트만 1과 1을 AND 연산하게 되므로 1로 살아남고, 나머지는 0이 됩니다. 따라서 교집합 연산이 됩니다. a & ~b 연산을 하게 되면 a 집합과 b의 여집합과 & 연산을 하게 됩니다. 즉, A - B 인 차집합 연산이 됩니다. 마지막으로, ^ 연산을 하게 되면 둘 중 하나에만 포함된 원소들만 1로 살아남게 됩니다. 집합의 크기 구하기 집합의 크기를 구하려면, 현재 1로 켜져 있는 비트의 수를 count 해야 됩니다. 따라서, 모든 비트를 순회해야 되고 재귀적으로 다음과 같이 구현할 수 있습니다. int bitCount(int x){ if(x == 0) return 0; return x % 2 + bitCount(x / 2); } x % 2 를 하면 마지막 비트를 얻게 되고, x / 2 를 하게 되면 마지막 비트를 삭제할 수 있습니다. 따라서, 모든 비트를 재귀적으로 순회할 수 있습니다. 모든 부분 집합 순회하기 어떤 집합의 모든 부분 집합을 순회하는 과정도 정말 간단하게 구현할 수 있습니다. for(int subset = set; subset; subset = (subset - 1) & set){ // subset은 set의 부분집합 중 하나. } 예를 들어, { A, B, D } 를 포함한 집합을 생각해보겠습니다. 모든 부분 집합은 공집합을 제외하고 { A }, { B }, { D }, { A, B }, { A, D }, { B, D }, { A, B, D } 가 존재합니다. 비트로 표현하면 다음과 같습니다. { A, B, D } 1101(2) { A, B } 1100(2) { A, D } 1001(2) { B, D } 0101(2) { A } 1000(2) { B } 0100(2) { D } 0001(2) 위에서 구현한 코드를 한 번 따라가 보겠습니다. set = 1101(2) = { A, B, D } 입니다. subset (subset - 1) (subset - 1) & set 1101(2) // { A B D } 1100(2) 1100(2) 1100(2) // { A B } 1011(2) 1001(2) 1001(2) // { A D } 1000(2) 1000(2) 1000(2) // { A } 0111(2) 0101(2) 0101(2) // { B D } 0100(2) 0100(2) 0100(2) // { B } 0011(2) 0001(2) 0001(2) // { D } 0000(2) 0000(2) // 종료 for문을 통해 모든 부분 집합을 다 순회하는 것을 확인할 수 있습니다. 위처럼 비트마스크를 이용하면 집합의 표현, 원소 추가, 원소 삭제, 원소 토글, 합집합, 교집합, 차집합 등등 다양한 연산들을 어떤 자료구조보다 빠르게 구현할 수 있습니다.
비트 마스크 (Bit Mask)
반응형
비트 마스크(Bit Mask) 기법은 말 그대로 비트(Bit)를 마스킹하는 기술 입니다. 비트를 마스킹 한다는 것은 &(AND 연산자), | (OR 연산자) 등의 비트 연산을 활용하여 정수의 이진 비트를 처리하는 작업이라고 이해하 실 수 있습니다. 비트 마스크 기법은 항상 사용할 수 있는 것은 아니지만 특정한 경우에 사용하면 매우 효율적 일 수 있습니다. 비트 마스크의 대표적인 장점을 소개하면 다음과 같습니다.
1. 메모리를 적게 사용할 수 있습니다.
2. 프로그램이 더욱 빠르게 동작 합니다.
3. 소스코드가 직관적으로 변경 됩니다.
일반적으로 정수 7이 있을 때 이것을 비트 형태로 표현하면 다음과 같습니다.
7 : 0000000 0000000 0000000 00000111 (2진수 비트, 32bit)
위와 같이 32개의 비트로 구성되게 됩니다. 이렇게 비트 형태로 특정한 변수를 직접적으로 다루면 효과적인 경우로는 무엇이 있을까요? 대표적인 예제로는 ‘출석 체크’가 있습니다. 학생이 32명이라고 가정 했을 때 각각 0번부터 31번까지 번호를 붙여봅시다. 이 떄 출석을 한 학생은 1로 표현하고, 출석을 하지 않은 학생은 0으로 표현할 수 있습니다. 예시로 5번, 7번 학생만 출석을 한 경우는 다음과 같습니다.
5번, 7번만 출석 : 0000000 0000000 0000000 01010000
다시 말해, 비트 마스크 기법을 이용하면 정수 하나만 이용해서 배열을 사용한 것과 같은 효과를 낼 수 있습니다.
이제 부터 실질적으로 비트 마스크 연산 문법을 알아보도록 합시다.
1. 2진수 형태로 출력하기
int(32비트)를 기준으로 보았을 때, 가장 왼쪽 비트부터 오른쪽 비트까지 하나씩 순회하면서 각 원소를 가지고 있는지 & 연산으로 확인하여 1 혹은 0 을 출력하면 됩니다.
// 2진수 형태로 출력하기 void show() { for (int i = 32; i > 0; i–) { if ((num & (1 << i - 1)) > 0) System.out.print(“1”); else System.out.print(“0”); } }
2. 모든 원소를 삭제하기
모든 원소를 삭제하고자 할 때는 단순히 변수를 0으로 초기화하면 됩니다. 기본적으로 컴퓨터는 2의 보수 체계를 가지고 있기 때문에 0으로 초기화하면 모든 비트가 0이 됩니다.
// 모든 원소를 삭제하기 void init() { num = 0; }
3. 모든 원소를 포함시키기
모든 원소를 포함시키고자 할 때는 변수에 -1을 넣으면 됩니다. 컴퓨터는 2의 보수 체계를 가지고 있기 때문에 -1로 초기화하면 모든 비트가 1이 됩니다.
1 : 0000000 0000000 0000000 0000001
1의 1의 보수 : 11111111 11111111 11111111 11111110
1의 2의 보수 : 11111111 11111111 11111111 11111111
따라서 -1을 넣어주면 모든 값을 포함시켜주게 됩니다.
// 모든 원소를 포함시키기 void full() { num = -1; }
4. 특정 원소 삭제하기
특정 원소를 삭제할 때는 (1 << i)에 NOT(~) 연산을 적용하여 변수 num와 AND(&) 연산을 수행하면 됩니다. ~(1 << i)는 특정 위치의 비트만 0이고 나머지는 전부 1이기 때문입니다. (1 << 32) : 10000000 00000000 00000000 00000000 (1 << 31) : 01000000 00000000 00000000 00000000 ~(1 << 32) : 01111111 11111111 11111111 11111111 ~(1 << 31) : 10111111 11111111 11111111 11111111 이기 때문에 num 과 AND연산(&)을 수행하면 특정 원소만 0을 포함 시킵니다. // 특정 원소를 삭제하기 void drop(int i) { num &= ~(1< 1; }
7. 특정 원소를 토글하기
특정 원소를 토글하고자 할 때는 (1< 0; i–) { if ((num & (1 << i - 1)) > 0) System.out.print(“1”); else System.out.print(“0”); } } // 모든 원소를 삭제하기 void init() { num = 0; } // 모든 원소를 포함시키기 void full() { num = -1; } // 특정 원소를 삭제하기 void drop(int i) { num &= ~(1< 1; } // 마지막 원소 구하기 int getLast() { return num & -num; } // 마지막 원소 삭제하기 void dropLast() { num &= (num – 1); } } }
반응형
[알고리즘] 비트(Bit)와 비트마스크(BitMask) 정리 (Java)
비트(bit)
비트(binary digit)는 데이터를 나타내는 최소 단위로 이진수의 한자라인 0 또는 1의 값을 가진다. 부호 없는 N비트 정수형 변수는 N자리의 이진수로 나타낼 수 있다. 이때 비트가 표현하는 값은 2^0 ~ 2^N-1까지이다.
여기서 2^N-1에 해당하는 비트값을 최상위 비트(Most Significant Bit)라 하고, 2^0에 해당하는 비트값을 최하위 비트(Least Significant Bit)라고 한다.
예를 들어 부호없는 4비트 정수형은 네 자리 이진수로 표시할 수 있는 모든 정수를 나타낼 수 있다. 아래 그림과 같이 4칸의 공간에 이진수 0 또는 1을 넣은 모든 경우의 수를 의미한다. 이때 비트가 표현하는 값은 2^0~2^3이다.
비트 표현법
여기서는 2^3이 최상위 비트이고 2^0에 해당하는 비트값(1)이 최하위이다.
비트 연산자 (java 기준)
비트 연산자는 피연산자의 각 비트들을 대상으로 연산이 이루어지며 총 4개의 연산자가 있다.
구분 연산자 의미 설명 비트연산자 & 비트 단위의 AND 두 정수를 한 비트씩 비교하면서 양쪽 비트가 모두 1이면 결과도 1이고 나머지는 0을 반환 | 비트 단위의 OR 두 정수를 한 비트씩 비교하면서 양쪽 비트 중 하나라도 1이면 결과가 1이고 나머지는 0을 반환 ^ XOR(배타적 OR) 두 정수를 한 비트씩 비교하면서 양쪽 비트가 서로 다르면 1, 같으면 0을 반환 ~ NOT 정수 하나의 각 비트를 1이면 0, 0이면 1로 바꾸는 연산 비트 이동연산자 << 정수 a를 왼쪽으로 b비트 만큼 이동 (빈자리는 0으로 채워짐, MSB가 1이 되면 음수로 바뀜) >> 정수 a를 오른쪽으로 b비트 만큼 이동 (빈자리는 정수 a의 MSB와 같은 값으로 채워짐) >>> 정수 a를 오른쪽으로 b비트 만큼 이동 (빈자리는 0으로 채워짐)
예제로 보면 다음과 같다.
public static void main(String[] args) { int x = 10; // 2진수로 변환시 1010 int y = 12; // 2진수로 변환시 1100 System.out.println(“x = \t” + Integer.toBinaryString(x)); System.out.println(“y = \t” + Integer.toBinaryString(y)); System.out.println(“x|y = \t” + Integer.toBinaryString(x|y)); System.out.println(“x&y = \t” + Integer.toBinaryString(x&y)); System.out.println(“x^y = \t” + Integer.toBinaryString(x^y)); System.out.println(“~x = \t” + Integer.toBinaryString(~x)); // int는 4byte = 32bit이기때문에 앞에 28개의 1이 출력됨 int a = -127; // 1111 1111 1111 1111 1111 1111 1000 0001 int shift_a = a>>1; // 1111 1111 1111 1111 1111 1111 1100 0000 int ns_shift_a = a>>>1; // 0111 1111 1111 1111 1111 1111 1100 0000 System.out.println(“a =\t” +a+”,”+ Integer.toBinaryString(a)); System.out.println(“a>>1 =\t” +(a>>1)+”,”+ Integer.toBinaryString(a>>1)); System.out.println(“a>>>1 =\t” +(a>>>1)+”,”+ Integer.toBinaryString(a>>>1)); }
toBinaryString() 메서드는 단지 비트연산자가 컴퓨터 내부에서 어떻게 처리되는지 문자열로 표현해주기 위해 사용했다.
결과값
비트마스크 (bit mask)
컴퓨터는 모든 CPU는 이진수를 이용해 모든 자료를 표현한다. 이진수를 이용해 연산을 하면 매우 빠르게 연산이 가능하고 이 특징을 이용해 자료구조 쓰는 기법을 비트마스크(bit mask)라고 한다.
– 이진수는 0 또는 1을 이용하므로 하나의 비트(bit)가 표현할 수 있는 경우는 두 가지이다.
– 보통 어떤 비트가 1이면 ” 켜져 있다 “라고 말하며, 0이면 ” 꺼져 있다 “라고 말한다.
비트마스크 장점
1. 다른 자료 구조에 비해 수행 시간이 더 빠르다.
→ 비트마스크 연산은 bit 연산이기 때문에 O(1)에 구현되는 것이 많다. 따라서 다른 자료구조를 이용하는 것보다 훨씬 빠르게 동작하게 된다.
2. 비트 연산자를 사용하여 코드가 더 간결해진다.
→ 위에 설명한 다양한 집합 연산들을 비트연산자로 한 줄로 작성할 수 있기 때문에 일반 데이터를 반복문, 조건문으로 비교했을 때보다 훨씬 간결하다.
3. 비트마스크를 사용하여 더 작은 메모리를 사용할 수 있다.
→ 개인적으로, 비트마스크를 이용하는 가장 큰 이유 라고 생각한다.
간단한 예시로, bit가 10개인 경우에는 각 bit당 두 가지 경우를 가지기 때문에 2^10가지의 경우를 10bit 이진수 하나로 표현이 가능하다. (ex. 10개의 발전소 중 1,3,4,5번 발전소 on -> 0000 0111 01)
→ 이처럼 하나의 정수로 매우 많은 경우의 수를 표현할 수 있기 때문에 메모리 측면에서 효율적이며, 더 많은 데이터를 미리 계산해서 저장해 둘 수 있는 장점이 있다. (DP에 매우 유용하다)
비트마스크를 이용한 집합 구현
비트마스크를 이용한 집합 구현은 가장 대표적이고, 자주 쓰이는 방법이다. 하나의 bit가 하나의 데이터 상태를 의미한다. bit가 1이면 해당 원소가 집합에 포함되어 있다는 의미이고, 0이면 포함되어 있지 않다는 의미이다. 따라서, N비트는 N개의 원소를 갖는 집합의 부분집합들을 모두 표현할 수 있다.
A를 10개의 집합의 상태를 나타내는 변수라고 가정하고 연산을 살펴보자. (0번째 ~ 9번째 원소)
연산 사용 예시 공집합과 꽉 찬 집합 구하기 A = 0; / A = (1 << 10) - 1; 원소 추가 A |= (1 << k); 원소 삭제 A &= ~(1 << k); 원소의 포함 여부 확인 if((A & (1 << k)) == (1 << k)) 원소의 토글(toggle) A ^= (1 << k); 두 집합에 대해서 연산 A | B → A와 B의 합집합 A & B → A와 B의 교집합 A & (~B) → A에서 B를 뺀 차집합 A ^ B → A와 B중 하나에만 포함된 원소들의 집합 집합의 크기 구하기 int bitCount(int A){ if(A == 0) return 0; return A%2 + bitCount(A / 2); } [내장 명령어] gcc/g++ → __builtin_popcount(A) visual C++ → __popcnt(A) Java → Integer.bitCount(A) 최소 원소 찾기 int first = A & (-A); 최소 원소 지우기 A &= (A - 1); 모든 부분 집합 순회하기 for (int subset = A ; subset>0; subset = ((subset – 1) & A)){ }
공집합과 꽉 찬 집합 구하기
☛ 기본적으로 공집합은 bit가 모두 꺼진 상황이기 때문에 상수 0이 공집합을 표현한다. 반대로 꽉 찬 집합은 bit가 모두 켜진 상황이기 때문에 1111111111(2) 의 값으로 표현한다.
원소 추가
☛ A 집합에 특정 원소를 추가하는 방법이다. 원소에 해당하는 bit만 켜야 하기 때문에 해당 bit를 항상 1로 만드는 연산이 필요하기 때문에 따라서 OR 연산 을 이용한다.
원소 삭제
☛ A 집합에 포함된 특정 원소를 삭제하는 방법이다. A에 k번째 원소의 포함 여부와 상관없이 해당 bit를 끄기 위해서는 AND 연산 을 이용해야 한다.
1<
subset-1 : 1100 2) 1100 > subset-1 : 1011
3) 1001 > subset-1 : 1000
4) 1000 > subset-1 : 0111
5) 0101 > subset-1 : 0100
6) 0100 > subset-1 : 0011
7) 0001 > subset-1 : 0000
비트필드를 이용한 DP문제
위의 비트마스킹을 어느정도 이해했으면 해당 문제를 풀어보자
해당 문제는 boolean으로 0~9의 상태를 하나하나 체크해주면 시간초과가 발생하고 복잡해지므로 비트마스크를 사용하여 계단수를 구해야 한다. dp 3차배열을 사용하여 다음과 같이 비트필드를 사용하여 메모리 공간과 연산을 줄일 수 있다.
i : i자리 숫자 , j 끝나는 숫자 , k 마킹된 숫자
j=9, 10 0000 0000 (9로 끝나는 숫자)
k =1, 10 0000 0001 (9로 끝나는 숫자, 0,9 사용)
k =2, 10 0000 0010 (9로 끝나는 숫자, 1,9 사용)
…
k = 9, 10 0000 1001 (9로 끝나는 숫자, 0,3,9 사용)
…
k = 1023, 11 1111 1111 (9로 끝나는 숫자, 0~9 모두사용)
이해가 쉽게 예시를 몇개 풀어보자
1) 2자리 숫자, 끝자리 숫자는 3, (2,3)이 포함된 수는?
더보기 > i=2, j=3, k = 12 (00 0000 1100) > 답 : 23 , 1개
2) 3자리 숫자, 끝자리 숫자는 4, (2,3,4)이 포함된 수는?
더보기 > i=3, j=4, k= 28 (00 0001 1100) > 답: 234 , 1개
3) 2자리 숫자, 끝자리 숫자 3, (2,3,4)이 포함된 수는?
더보기 > 이는 두개의 dp값을 구해야 한다. > i=2, j=3, k = 12 (00 0000 1100) > 23 > i=2, j=3, k= 24 (00 0001 1000) > 43 > 답 : 23,43 (dp[2][3][12] + dp[2][3][24] = 2개)
점화식 코드
int bit = k | (1<
[알고리즘 개념] 비트마스크(Bitmask)
비트(Bit)
컴퓨터는 이진수를 통해서 모든 자료를 표현한다.
여기서 사용하는 이진수가 데이터의 최소 단위 Bit(binary Disit)이다.
비트는 0 또는 1의 값을 가지며, n개의 비트는 2^0~2^n-1까지 표현 가능하다.
1 = 2^0 = 1 10 = 2^1 = 2 100 = 2^2 = 4 111 = 2^2+2^1+2^0 = 7 3자리의 비트는 1~2^n-1 까지 표현가능
비트 연산자 및 용어 정리
최상위 비트(MSB): 2^n-1 비트
최하위 비트(LSB): 2^0 비트
비트가 켜져있다: 1
비트가 꺼져있다: 0
int는 4byte 총 32비트로 되어있다. ( 최상위 비트는 부호비트 1: -, 0:+) int -1 = bit 11111111111111111111111111111111 int -2 = bit 11111111111111111111111111111110 비트가 꺼지는걸로 표기
연산자 의미 설명 a & b AND 정수 a,b 를 비트 1개씩 비교하여 둘다 1이면 결과 1, 아니면 0 a | b OR 정수 a,b 를 비트 1개씩 비교하여 둘 중 하나가 1이면 1, 아니면 0 a^b XOR 정수 a,b 를 비트 1개씩 비교하여 두개가 다르면 1, 같으면 0 ~a NOT 정수 a 각 비트가 1이면 0, 0이면 1로 변환 a<>b 정수 a를 오른쪽으로 b비트만큼 이동(빈자리 a의 MSB) a>>>b 정수 a를 오른쪽으로 b비트만큼 이동(빈자리 0)
연산자 실행코드
public class Test { public static void main(String[] args) { int plus = 1; int Minus = -1; // 1밖에 안보이지만 앞에 다 0으로 채워져 있음 System.out.println(“1: ” + Integer.toBinaryString(plus)); System.out.println(“-1: ” + Integer.toBinaryString(Minus)); int a = 4; // 100 int b = 7; // 111 // 비트형태로 출력 System.out.println(“a bit: ” + Integer.toBinaryString(a)); System.out.println(“b bit: ” + Integer.toBinaryString(b)); // 비트 연산 System.out.println(“a&b: ” + Integer.toBinaryString(a&b)); System.out.println(“a|b: ” + Integer.toBinaryString(a|b)); System.out.println(“a^b: ” + Integer.toBinaryString(a^b)); System.out.println(“~a: ” + Integer.toBinaryString(~a)); a = -16; // shift 연산 System.out.println(“a bit: ” + Integer.toBinaryString(a)); System.out.println(“a<<2: int("+ (a<<2) +") bit(" + Integer.toBinaryString(a<<2) +")"); System.out.println("a>>2: int(“+ (a>>2) +”) bit(” + Integer.toBinaryString(a>>2) +”)”); // 빈자리에 0이 들어와서 부호비트가 0이 되었기때문에 양수로 변환 System.out.println(“a>>>2: int(“+ (a>>>2) +”) bit(” + Integer.toBinaryString(a>>>2) +”)”); } }
결과값
키워드에 대한 정보 비트 마스크
다음은 Bing에서 비트 마스크 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 [DANCE] MVSK – Kep1er (케플러) | Dance Cover Practice
- 큰소영
- 쏘하
- ARTBEAT
- Dance
- Cover
- MVSK
- Kep1er
- 케플러
- AB PROJECT
- 방구석여기서요
- 연습
- Practice
YouTube에서 비트 마스크 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 [DANCE] MVSK – Kep1er (케플러) | Dance Cover Practice | 비트 마스크, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.