紫书刷题进行中,题解系列点这里
习题4-5 UVA1590 IP Networks(37行AC代码)
题目大意
给定若干个IP地址,求包含所有IP的最小IP网络。
- IP地址:4个字节,每个字节用十进制表示,并用点分割,形如
xxx.xxx.xxx.xxx,无前导0,每个十进制在[0,255] - IP网络:由子网地址和子网掩码构成,二者形式和IP地址一样,二者存在制约关系,假设有n(处于[0,32]),那么在二者的二进制表示中
- 子网掩码的前n位为1,后32-n位为0
- 子网地址的前n位任意,后32-n位为0
- 假设n=24,子网地址假设为
198.123.123.0,子网掩码255.255.255.0,那么198.123.123.0~198.123.123.255均属于该IP网络
思路分析
可先找出所有IP地址中最大和最小值,再计算最大小值的二进制形式的最长公共子串长度len(从头开始),接着将最小值二进制低32-n置0,构造前n位为1,后32-n位为0的子网掩码。
- 比较大小:可用stringstream分割IP地址,并计算出32位的数字,从而得到最大和最小值
- 位处理:可用
bitset完成二进制字符串和数值间相互转化,每个位的0/1设置
AC代码(C++11,bitset,位运算)
#include<bits/stdc++.h>
using namespace std;
void binstrToIP(string s) { // 二进制字符串转为IP形式
for (int i = 0; i < 4; i ++) {
bitset<8> bt(s.substr(i*8,8));
printf("%u%s", bt.to_ulong(), i == 3 ? "\n" : ".");
}
}
int main() {
int n;
while (cin >>n) {
string smax, smin, smask, s, st;
unsigned umin=UINT32_MAX, umax = 0;
while (n --) {
cin >>s;
stringstream input(s);
unsigned uint = 0;
while (getline(input, st, '.')) { // 分割每个部分
uint = (uint << 8) + (unsigned)stoi(st); // 256进制
}
if (umin >= uint) umin = uint, smin = s; // 最小值
if (umax <= uint) umax = uint, smax = s; // 最大值
}
bitset<32> bmin(umin), bmax(umax), bmask(0xffffffffu);
smin = bmin.to_string(); smax = bmax.to_string(); // 转为2进制字符串
int cnt = 0;
for (int i = 0; i < 32; i ++) { // 统计从头开始的公共子串长度
if (smin[i] == smax[i]) cnt ++;
else break;
}
for (int i = 0; i < 32-cnt; i ++) { // 设置IP地址和掩码低32-cnt位为0
bmin.reset(i); bmask.reset(i); // 注意bitset逆序存储
}
binstrToIP(bmin.to_string()); binstrToIP(bmask.to_string());
}
return 0;
}
本文提供了一种解决UVA1590 IPNetworks问题的方法,通过找出给定IP地址集合的最大和最小值,计算二进制表示下的最长公共前缀,以此确定包含所有IP的最小IP网络。使用C++11、bitset和位运算实现AC代码。
&spm=1001.2101.3001.5002&articleId=104148842&d=1&t=3&u=f9c024c0acb44b899e3982af13070c00)
5563

被折叠的 条评论
为什么被折叠?



