Alex is administrator of IP networks. His clients have a bunch of individual IP addresses and he decided to group all those IP addresses into the smallest possible IP network.
Each IP address is a 4-byte number that is written byte-by-byte in a decimal dot-separated notation “byte0.byte1.byte2.byte3” (quotes are added for clarity). Each byte is written as a decimal number from 0 to 255 (inclusive) without extra leading zeroes.
IP network is described by two 4-byte numbers — network address and network mask. Both network address and network mask are written in the same notation as IP addresses.
In order to understand the meaning of network address and network mask you have to consider their binary representation. Binary representation of IP address, network address, and network mask consists of 32 bits: 8 bits for byte0 (most significant to least significant), followed by 8 bits for byte1, followed by 8 bits for byte2, and followed by 8 bits for byte3.
IP network contains a range of 2n IP addresses where 0 ≤ n ≤ 32. Network mask always has 32−n first bits set to one, and n last bits set to zero in its binary representation. Network address has arbitrary 32 −n first bits, and n last bits set to zero in its binary representation. IP network contains all IP addresses whose 32 −n first bits are equal to 32 −n first bits of network address with arbitrary n last bits. We say that one IP network is smaller than the other IP network if it contains fewer IP addresses.
For example, IP network with network address 194.85.160.176 and network mask 255.255.255.248 contains 8 IP addresses from 194.85.160.176 to 194.85.160.183 (inclusive).
Input
The input file will contain several test cases, each of them as described below.
The first line of the input file contains a single integer number m (1 ≤m≤ 1000). The following m lines contain IP addresses, one address on a line. Each IP address may appear more than once in the input file.
Output
For each test case, write to the output file two lines that describe the smallest possible IP network that contains all IP addresses from the input file. Write network address on the first line and network mask on the second line.
Sample Input
3
194.85.160.177
194.85.160.183
194.85.160.178
Sample Output
194.85.160.176
255.255.255.248
HINT
题目的意思就是给你一堆网址,让你找出所有网址相同的部分和不相同的部分,然后求出不相同的部分的位数n(网址是由四个数每一个数占有8位),然后求出最小的网络地址,也就把求得的n位全部改成0,然后按照每八位一个数的方式打印出来,同样打印子网掩码也是将最后n位补上0,然后按照子网的方式打印。
解决思路:
这个题实际上暗示了让我们使用位运算,但是如何使用位运算?如何表示每一个数?如何求出n?
因为int型数字有32位,二每一个子网有四个数字然后每八个是一个数。不能直接用int值表示4个数,因此我们采取一个数字一个数字来表示的方法。
对于位运算,我们需要知道从哪里开始使用位运算,也就是判断给定的网址从哪里开始出现不同。这里采用的方式是对每一个网址的每一个数都放到一个数组的一维里面,然后对其进行排序,如果最后一个和第一个出现不一样那么就从这里开始位运算。
位运算是干什么的?
这里我们要判断n的大小,不能仅仅从十进制大小进行判断,例如8和9的二进制分别是1000和1001,他们只有最后一个位是不同的,前三位都是相同的。因此位运算就是来判断n的大小不仅仅从10进制数来判断。
那么,如何求出n的大小?
我们是将32位分成八位进行显示的,因为后n位的二进制值都是0所以如果实际的n是9位,那么最后八位都是0显示的十进制也是0,因此我们只需要将四位数中从左往右算第一个出现不同的数里面求出他们不一样的位数即可,剩下的全部为0。因为各个数前面的位都是相同的,只有后面的是不同的,采取位运算,令两个数字每次右移一个位知道两个数相同为止。比如1000和1001右移一位编程100和100是相同的,就求出来n是1。然后将这一个编码值先右移n位然后左移n位,后面n位就自动变成0。然后输出结果。
对于子网掩码大同小异。操作只需要和上面的位运算相同即可。
Accepted
#include<stdio.h>
#include<stdlib.h>
int bit(int a, int b) //求出n的位数
{
int i = 0; //计算n的位数
while (a != b)
{
a=a>>1; //a,b同时右移一位直到相等
b=b>>1;
i++;
}
return i;
}
int cmp(const void* a, const void* b) //快排的比较函数
{
return *(int*)a - *(int*)b;
}
int main()
{
int m,n;
while (scanf("%d", &m) != EOF) //m是网址的个数
{
getchar();
int ip[4][1002] = { 0 }; //ip有四行,每一行的每一个元素都是一个网址相同位置的数字
for (int i = 0;i < m;i++)
{
for (int j = 0;j < 4;j++) //读入
{
int num = 0;
char temp;
while ((temp = getchar()) != '.' && temp != '\n')num = num * 10 + temp - '0';//将读入的字符转化位整数
ip[j][i] = num;
}
}
int arr[4] = { 255,255,255,255 }; //子网掩码初始化为最大
for (int i = 0;i < 4;i++)
{
qsort(ip[i], m, sizeof(int), cmp); //排序每一行,找到位运算的开始数字
if (ip[i][0] != ip[i][m - 1]) //开始位运算
{
n = bit(ip[i][0], ip[i][m - 1]); //求得移动位数
ip[i][m - 1]=ip[i][m - 1] >> n; //先右移后左移,将后面的n位清零
ip[i][m - 1]=ip[i][m - 1] << n;
arr[i] = arr[i] >> n; //子网掩码清零
arr[i]=arr[i] << n;
printf("%d", ip[i][m - 1]); //输出
if (i != 3)printf(".");
for (i++;i < 4;i++) //后面的数字清零输出
{
printf("0");
arr[i] = 0;
if (i != 3)printf(".");
}
}
else {
printf("%d", ip[i][0]);
if (i != 3)printf(".");
}
}
printf("\n");
printf("%d.%d.%d.%d\n", arr[0], arr[1], arr[2], arr[3]);
}
}