题目翻译(取自洛谷):
亚历克斯是IP网络的管理员。他的客户每个人有一组单独的IP地址,他决定将所有IP地址分组到最小可能的IP网络中。
每个IP地址有四个部分组成,每个部分用小数点分离。格式如a,b,c,d每个部分都是一个十进制的数(0≤这个数≤255)且没有多余的前导零。
IP网络由两个4各部分的数字——网络地址和网络掩码组成。网络地址和网络掩码和IP地址写入方式相同。为了理解网络地址和网络掩码的含义,我们将它们用二进制来表述。IP地址、网络地址和网络掩码的二进制都由32位组成:a的8位(从最重要到最不重要),其次是b的8位,其次是c的8位,其次是d的8位。
IP网络包含一个2n个IP地址的范围,其中所有n>32。网络掩码始终存在32~n个第一部分设置为一,n个最后部分在二进制表示中设置为零。网络地址已任意32个n个第一部分,n个最后部分在其二进制表示中设置为零。IP网络所有的32个n位第一位相当于32位n个任意位的网络地址的所有IP地址最后一位。
我们说,一个IP网络比其他IP网络更小,那么它包含更少的IP地址。
输入输出格式
输入格式:
有多个测试数据。
输入文件的第一行包含一个整数m。下面m行都是一个IP地址。IP地址可能重复。
输出格式:
每个测试数据在第一行写上网络地址,在第二行写上网络掩码。 网络地址和网络掩码代表的IP网络包括所有IP地址且最小。
样例输入输出:
样例输入#1
3
194.85.160.177
194.85.160.183
194.85.160.178
样例输出#1
194.85.160.176
255.255.255.248
样例说明
一个IP网络的网络地址是194.85.160.176它的网络掩码是255.255.255.248
那么这个IP网络包含8个IP地址从194.85.160.176到194.85.160.183
说明
0 ≤ n ≤ 32,1 ≤ m ≤ 1000
解题重点思路
1、确定n(全为0的位数)
2、10进制ip转2进制ip的函数
3、2进制ip转10进制ip的函数
4、第1点需要利用第2点在2进制下将所有ip进行比较。
5、实践自顶向下的实现模拟
代码(问题必回答):
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
using namespace std;
/******************************************************
IP地址
天大夏令营题目
*******************************************************/
typedef struct
{
int ip4[4];
}Ip;
Ip Ips[1010];
int binary[33];//存储二进制
int m;
void print_ip(Ip ip)
{
printf("%d.%d.%d.%d\n",ip.ip4[0],ip.ip4[1],ip.ip4[2],ip.ip4[3]);
}
void print_b()
{
for(int i=1;i<=32;i++)
{
if(i%8==0)
printf("%d|",binary[i]);
else
printf("%d",binary[i]);
}
printf("\n");
}
Ip get_10ip()
{
Ip newip;
for(int i=0;i<4;i++)
{
int tmp = 0,b=1;
for(int j=(i+1)*8;j>=1+8*i;j--)
{
tmp+=binary[j]*b;
b*=2;
}
newip.ip4[i]=tmp;
}
return newip;
}
void get_2ip(Ip ip)
{
memset(binary,0,sizeof(binary));
for(int i=0;i<4;i++)
{
int tmp = ip.ip4[i];
for(int j=(i+1)*8;tmp>0;j--)
{
binary[j]=tmp%2;
tmp/=2;
}
}
}
int get_n(int i)//获取不相同的位数n
{
int nn;
bool flag=true;
for(int n=i*8+1;flag&&n<=32;n++)
{
get_2ip(Ips[0]);
//print_b();
int x=binary[n];
for(int j=1;j<m;j++)
{
get_2ip(Ips[j]);
if(x!=binary[n])
{
nn=n;
flag=false;
break;
}
}
}
return 32-nn+1;
}
int main()
{
while(scanf("%d",&m)!=EOF)
{
for(int i=0;i<m;i++)
{
char left;
scanf("%d%c%d%c%d%c%d",&Ips[i].ip4[0],&left,&Ips[i].ip4[1],&left,&Ips[i].ip4[2],&left,&Ips[i].ip4[3]);
getchar();//读取多余回车
}
int di;//di为十进制下不相同的ip子节位置
bool flag=true;
for(int i=0;i<4&&flag;i++)
{
int tmp = Ips[0].ip4[i];
for(int j=1;j<m;j++)
{
if(tmp!=Ips[j].ip4[i])
{
di=i;
flag=false;
break;
}
}
}
//printf("di is in %d\n",di);
int n;
if(flag)//全都相同或者m=1
{
n=0;
}
else
{
n=get_n(di);
}
//printf("n is in %d\n",n);
get_2ip(Ips[0]);
for(int j=32;j>32-n;j--)
binary[j]=0;//将相应的位数全部设置为0
//print_b();
Ip result1 = get_10ip();
for(int j=1;j<=32-n;j++)
binary[j]=1;
Ip result2 = get_10ip();
print_ip(result1);
print_ip(result2);
}
return 0;
}