본문 바로가기
알고리즘/백준

[백준]1094막대기 C++

by 오오오니 2022. 3. 30.

비트마스킹 문제이다.

#include<iostream>

using namespace std;



int main()
{
	
	int temp = 0;
	for (int i = 0; i < 10; i++)
	{
		
		temp = (1 << i);
		cout << temp << endl;
	}
	


}

이 코드를 돌려보면 

이렇게 나온다. 

temp  -> 1     2^0=1

temp  ->10    2^1=2

temp -> 100  2^2=4 

temp -> 1000 2^3 =8

temp -> 10000 2^4 =16

.

.

temp ->1000000  2^6 =64

#include<iostream>

using namespace std;

//지민이가 가지고 있는 막대의 길이를 모두 더한다.처음에는 64cm 막대 하나만 가지고 있다.이때, 합이 X보다 크다면, 아래와 같은 과정을 반복한다.
//가지고 있는 막대 중 길이가 가장 짧은 것을 절반으로 자른다.
//만약, 위에서 자른 막대의 절반 중 하나를 버리고 남아있는 막대의 길이의 합이 X보다 크거나 같다면, 위에서 자른 막대의 절반 중 하나를 버린다.
//이제, 남아있는 모든 막대를 풀로 붙여서 Xcm를 만든다.

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	int x;
	cin >> x;
	int stick = 64;
	int half = 64;
	while (true)
	{
		if (stick != x)
		{
			half = half >> 1;
			//만약, 위에서 자른 막대의 절반 중 하나를 버리고 
			//남아있는 막대의 길이의 합이 X보다 크거나 같다면
			if (stick-half >= x)
			{
				stick -= half; //이제, 남아있는 모든 막대를 풀로 붙여서 Xcm를 만든다
			}
			
		}
		else
		{
			break;
		}
		
		
	}
	int count = 0;
	for (int i = 0; i < 7; i++)
	{
		if (stick&(1 << i))
			count++;
	}
	cout << count;
	
	
}

이렇게 풀어서 맞았는데 비트마스킹을 잘 활용 못한 것 같아서 다른 사람의 풀이를 찾아봤다

x의 비트를 세주는 방법으로 하면 몇 번 잘랐는지 알게 된다고 한다.

마지막 비트를 꺼주는 방법은 자기보다 1작은 수와 & 연산을 하면 된다고 한다.

ex) x= 10 ,  x-1=9

1010 & 1001 ->1000

이런식으로 x가 0이 될때까지 마지막 비트를 꺼주면서 count 해주면 된다.

또다른 방법은

1을 왼쪽으로 한칸씩 쉬프트하면서 X와 & 연산을 하는 것이다. 

x &(1<<i)     x의 i 번 째 비트가 1이면 저 식이 참이 되기 때문에 그럴 때마다 count해주면된다.

(0<=i<=6)

 

느낀점

문제를 그대로 직역해서 막대기를 자라는 것에 집중했는데

x를 보고 얼마나 잘랐는지 세어주는 방법으로도 할 수 있다는 것이 신기했다.

문제를 그대로 코드로 바로 옮기지 말고  거꾸로도 생각해봐야겠다.

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 15829 Hashing c++  (0) 2022.04.13
[백준] 10815숫자카드 c++  (0) 2022.04.03
[백준] 9461파도반수열 c++  (0) 2022.03.24
[백준]9663N-Queen c++  (0) 2022.03.19
[백준] 9095 1, 2, 3 더하기 c++  (0) 2022.03.19