🧪 2064 IP 주소
난이도 : 🌟 골드 3
유형 : 비트마스킹
https://www.acmicpc.net/problem/2064
📝 문제

네트워크에 연결되어 있는 컴퓨터들은 각각 하나의 IP 주소를 갖게 된다. 그리고 이러한 IP 주소를 갖는 컴퓨터들이 여러 개 모여서 하나의 IP 네트워크를 구성하게 된다. IP 네트워크는 ‘네트워크 주소’와 ‘네트워크 마스크’라는 두 개의 정보로 표현된다.
IP 주소는 네 개의 바이트로 구성되어 있으며, 각각을 10진수로 나타내고(앞에 0을 붙이지 않은 형태로) 사이에 점을 찍어 주소를 표현한다. 바이트이기 때문에 각각의 수는 0부터 255까지의 값을 갖게 된다. 네트워크 주소와 네트워크 마스크 역시 같은 형식으로 나타낸다.
IP 네트워크에 대해 올바르게 이해하기 위해서는 위와 같은 주소를 2진수로 이해하면 된다. 즉, 각각의 바이트를 8자리의 이진수로 나타내고, 이를 네 개 붙여놓은(앞에서부터) 32자리의 이진수를 생각해 보자. IP 네트워크에는 기본적으로 2m 개의 컴퓨터(혹은 IP 주소)가 할당될 수 있다. 이 경우의 네트워크 주소는 앞의 32-m 자리가 임의의 수(0 또는 1)로 구성되어 있고, 뒤의 m자리는 0으로 채워지게 된다. 네트워크 마스크는 앞의 32-m 자리가 1로 채워져 있고, 뒤의 m자리는 0으로 채워지게 된다. 이와 같은 IP 네트워크에는 앞의 32-m 자리가 네트워크 주소와 일치하는 모든 IP들이 포함되게 된다.
예를 들어 네트워크 주소가 194.85.160.176이고, 네트워크 마스크가 255.255.255.248인 경우를 생각해 보자. 이 경우, 이 네트워크에는 194.85.160.176부터 194.85.160.183까지의 8개의 IP 주소가 포함된다.
어떤 네트워크에 속해있는 IP 주소들이 주어졌을 때, 네트워크 주소와 네트워크 마스크를 구해내는 프로그램을 작성하시오. 답이 여러 개인 경우에는 가장 크기가 작은(포함되는 IP 주소가 가장 적은, 즉 m이 최소인) 네트워크를 구하도록 한다.
입력
첫째 줄에 정수 n(1 ≤ n ≤ 1,000)이 주어진다. 다음 n개의 줄에는 각 컴퓨터의 IP 주소가 주어진다.
출력
첫째 줄에 네트워크 주소를, 둘째 줄에 네트워크 마스크를 출력한다.
🧐 핵심 로직
1. 주어진 문제에서는 입력된 IP 주소들을 통해 공통 네트워크 주소와 서브넷 마스크를 계산한다.
2. IP 주소는 4개의 8비트 숫자로 구성되며, 점(.)으로 구분된다. 이를 처리하기 위해 split("\\\\.") 메서드를 사용하여 입력된 문자열을 숫자 배열로 분리한다.
3. subNetting() 메서드는 네트워크 주소와 서브넷 마스크를 계산하는 핵심 로직을 포함한다.
4. 먼저 networkAddress와 subnetMask를 빈 StringBuilder 객체로 초기화한다. 이후, 각 IP 주소의 각 8비트 값(즉, 각 옥텟)을 비교한다.
5. 각 옥텟에서 min 값은 모든 IP 주소들의 해당 옥텟 값에 대해 AND 연산을 수행하여 최소값을 계산한다. 반대로 max 값은 OR 연산을 통해 최대값을 계산한다.
6. 네트워크 주소는 각 옥텟의 min 값을 그대로 사용하고, 서브넷 마스크는 255 - (max - min)을 계산하여 생성한다.
7. flag 변수는 각 옥텟에서 최소값과 최대값이 다를 경우를 감지하며, 이후 옥텟들은 네트워크 주소와 서브넷 마스크에서 0으로 채워진다.
8. 마지막으로 생성된 StringBuilder에서 마지막 문자(.)를 제거하여 형식을 맞춘 후 출력한다.
💻 최종 코드 (152 ms)
import java.util.*;
import java.io.*;
public class Main {
static BufferedReader br;
static int n;
static StringBuilder networkAddress, subnetMask;
static String[][] ips;
public static void main(String[] args) throws Exception {
// br = new BufferedReader(new InputStreamReader(System.in));
br = new BufferedReader(new FileReader("input.txt"));
// split() 메서드에서 "."은 일반 문자열이 아니라 정규 표현식으로 해석
// 정규식에서 "."는 아무 문자(newline 제외)를 의미
// 따라서, 단순히 점(.)을 기준으로 나누려고 했더라도, 예상치 못한 동작을 할 수 있다
n = Integer.parseInt(br.readLine());
ips = new String[n][4];
for (int i = 0; i < n; i++) {
ips[i] = br.readLine().split("\\.");
}
subNetting();
// 마지막 "." 제거
networkAddress.deleteCharAt(networkAddress.length()-1);
subnetMask.deleteCharAt(subnetMask.length()-1);
System.out.print(networkAddress+"\n"+subnetMask);
br.close();
}
private static void subNetting() {
boolean flag = false;
networkAddress = new StringBuilder();
subnetMask = new StringBuilder();
for (int i = 0; i < 4; i++) {
int min = Integer.parseInt(ips[0][i]);
int max = Integer.parseInt(ips[0][i]);
for (int j = 1; j < n; j++) {
min = min & (Integer.parseInt(ips[j][i]));
max = max | (Integer.parseInt(ips[j][i]));
}
if (!flag) {
networkAddress.append(min).append(".");
subnetMask.append(255 - (max - min)).append(".");
} else {
networkAddress.append(0).append(".");
subnetMask.append(0).append(".");
}
if (min != max) flag = true;
}
}
}
'Hub Algorithm > 비트마스킹' 카테고리의 다른 글
[BOJ] 백준 14391 : 종이 조각 (java) (0) | 2025.01.05 |
---|