解题思路
这是一道网络地址处理问题,主要思路如下:
-
问题分析:
- CIDR是一种IP地址分类方法
- 需要去除被其他路由完全覆盖的路由
- 比较两个路由时需要考虑子网掩码长度
- 输出剩余的不重复路由
-
解决方案:
- 将IP地址转换为32位整数便于比较
- 使用位运算处理子网掩码
- 比较两个路由的网络地址部分
- 标记被覆盖的路由并最后输出未被覆盖的路由
-
实现细节:
- 使用位运算优化IP地址比较
- 正确处理子网掩码长度关系
- 维护路由的有效性标记
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
// 存储IP地址和掩码
vector<int> ip(n), mask(n);
vector<int> flag(n, 1); // 标记路由是否有效
// 读取输入
for(int i = 0; i < n; ++i) {
int a, b, c, d;
scanf("%d.%d.%d.%d/%d", &a, &b, &c, &d, &mask[i]);
// 将IP地址转换为32位整数
ip[i] = (a << 24) | (b << 16) | (c << 8) | d;
}
// 处理路由覆盖关系
int res = n;
for(int i = 0; i < n-1; ++i) {
for(int j = i+1; j < n; ++j) {
if(!flag[j]) continue;
if(mask[i] <= mask[j]) {
// 比较网络地址部分
int a = ip[i] >> (32-mask[i]);
int b = ip[j] >> (32-mask[i]);
if(a == b) {
flag[j] = 0; // j被i覆盖
--res;
}
} else {
int a = ip[i] >> (32-mask[j]);
int b = ip[j] >> (32-mask[j]);
if(a == b) {
flag[i] = 0; // i被j覆盖
--res;
break;
}
}
}
}
// 输出结果
cout << res << endl;
int t = 0xFF;
for(int i = 0; i < n; ++i) {
if(flag[i]) {
int temp = ip[i];
int d = temp & t;
temp >>= 8;
int c = temp & t;
temp >>= 8;
int b = temp & t;
temp >>= 8;
int a = temp & t;
printf("%d.%d.%d.%d/%d\n", a, b, c, d, mask[i]);
}
}
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] ip = new int[n];
int[] mask = new int[n];
boolean[] flag = new boolean[n];
Arrays.fill(flag, true);
// 读取输入
for(int i = 0; i < n; i++) {
String[] parts = sc.next().split("[./]");
ip[i] = (Integer.parseInt(parts[0]) << 24) |
(Integer.parseInt(parts[1]) << 16) |
(Integer.parseInt(parts[2]) << 8) |
Integer.parseInt(parts[3]);
mask[i] = Integer.parseInt(parts[4]);
}
// 处理路由覆盖关系
int res = n;
for(int i = 0; i < n-1; i++) {
for(int j = i+1; j < n; j++) {
if(!flag[j]) continue;
if(mask[i] <= mask[j]) {
int a = ip[i] >>> (32-mask[i]);
int b = ip[j] >>> (32-mask[i]);
if(a == b) {
flag[j] = false;
--res;
}
} else {
int a = ip[i] >>> (32-mask[j]);
int b = ip[j] >>> (32-mask[j]);
if(a == b) {
flag[i] = false;
--res;
break;
}
}
}
}
// 输出结果
System.out.println(res);
for(int i = 0; i < n; i++) {
if(flag[i]) {
int temp = ip[i];
System.out.printf("%d.%d.%d.%d/%d\n",
(temp >>> 24) & 0xFF,
(temp >>> 16) & 0xFF,
(temp >>> 8) & 0xFF,
temp & 0xFF,
mask[i]);
}
}
}
}
def ip_to_int(ip_str):
parts = list(map(int, ip_str.split('.')))
return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]
def int_to_ip(num):
return f"{(num >> 24) & 0xFF}.{(num >> 16) & 0xFF}.{(num >> 8) & 0xFF}.{num & 0xFF}"
def main():
n = int(input())
ip = []
mask = []
flag = [True] * n
# 读取输入
for _ in range(n):
line = input().strip()
addr, m = line.split('/')
ip.append(ip_to_int(addr))
mask.append(int(m))
# 处理路由覆盖关系
res = n
for i in range(n-1):
for j in range(i+1, n):
if not flag[j]:
continue
if mask[i] <= mask[j]:
a = ip[i] >> (32-mask[i])
b = ip[j] >> (32-mask[i])
if a == b:
flag[j] = False
res -= 1
else:
a = ip[i] >> (32-mask[j])
b = ip[j] >> (32-mask[j])
if a == b:
flag[i] = False
res -= 1
break
# 输出结果
print(res)
for i in range(n):
if flag[i]:
print(f"{int_to_ip(ip[i])}/{mask[i]}")
if __name__ == "__main__":
main()
算法及复杂度
- 算法:位运算 + 双重循环比较
- 时间复杂度:
-
为路由数量
- 空间复杂度:
- 存储路由信息