본문 바로가기

백준/골드

[백준 2064번] IP 주소 (C++)

문제링크 : https://www.acmicpc.net/problem/2064

 

2064번: IP 주소

네트워크에 연결되어 있는 컴퓨터들은 각각 하나의 IP 주소를 갖게 된다. 그리고 이러한 IP 주소를 갖는 컴퓨터들이 여러 개 모여서 하나의 IP 네트워크를 구성하게 된다. IP 네트워크는 ‘네트워

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX 987654321
#define pii pair <int, int>

int ip2[1001];

void func(int n) // 32비트수를 십진수로 변환
{
	int len = 24;
	for(int i=0; i<4; i++)
	{
		cout << ((n >> len) & (1 << 8)-1); //8개씩 끊어서 출력
		if(i==3) continue;
		cout << '.';
		len -= 8;
	}
	cout << '\n';
}

int main() 
{
	ios_base::sync_with_stdio(false); 
	cin.tie(0);
   
	int N;
	cin >> N;
	string ip, tmp;

	for(int i=0; i<N; i++)
	{
		cin >> ip;
		istringstream ss(ip);
		while(getline(ss, tmp, '.')) //'.'기준으로 자르기
		{
			ip2[i] <<= 8; //자리 만들기 (하나당 8칸)
			ip2[i] |= stoi(tmp); //더해주기 (or 연산)
		}
	}

	int result = 0;
	for(int i=31; i>=0; i--)
	{
		bool check = true;
		for(int j=1; j<N; j++)
		{
			if((ip2[0] & (1<<i)) != (ip2[j] & (1<<i))) //비트가 달라지는지 체크
			{
				check = false;
				break;
			}
		}
		if(check) result |= (1<<i); //비트가 같으면 1로 채워주기
		else break;
	}

	func(result & ip2[0]); //네트워크 주소
	func(result); //네크워크 마스크

    return 0;
}

비트마스킹 문제이다.

처음에 '.'를 기준으로 짜르는 걸 보자마자 파이썬의 split이 떠올랐다.

C++에서도 그런 방식으로 할 수 있나하여 찾아보니 istringstream ss(str)이라는 문자열 파싱 함수를 찾았다.

이를 통해서 '.'를 기준으로 자르고 자른 것은 문자열이기에 정수로 변환하고 or 연산을 통해 저장했다.

 

다음으로 비트가 달라지는 지를 체크해줘야한다.

비트가 달라지기 전까지는 1로 채워주다가, 달라지는 순간부터는 0이 된다.

아직 비트마스킹이 미숙해서 여기서도 검색의 도움을 빌렸다.

 

처음에 단순히 위에서 만들어준 or 연산을 통해 만들어진 값을 비교하면 되는 알았는데 이상한 값이 나왔다.

위에 값에서 또 (1<<i)를 and 연산을 해준 값이랑 비교를 해주어야 제대로 된 비교가 가능했다.

 

저장된 값은 비트로 된 것이 아니라 정수형태로 들어가 있는 것이기 때문에 비트 연산을 통해야 다시 내가 원하는 비트 상태로의 변환이 가능했다.

 

그리고 문제에서 출력은 다시 10진수의 형태로 출력한다.

따라서 위의 과정을 통해서 만들어진 32비트수를 다시 10진수로 변환하는 과정이 필요하다.

이는 8개로 된 4개의 수를 첫 8개씩 오른쪽끝으로 밀고 이를 (1<<8)-1 과 and 연산을 통해서 구해주었다.