题目:https://vjudge.net/problem/UVA-1590
听说这题用位运算能大幅简化,奈何我不会用。
思路:既然要找个最小范围,自然要知道上限下限,找出最大的ip和最小的ip,然后转换成二进制,比对这两个ip的二进制,找出第一个不相同的位置。在这个位置之前的二进制位最小的不变,最大的赋值为1;在这个位置之后的每个二进制位(包括这个位置),将两ip都赋值为0。再将处理后的这两个ip转换回十进制。那么原来最小的ip就成了网络地址(network address),原来最大的ip就成了子网掩码(network mask)。
语言:c++
#include <cstdio>
#include <iostream>
#include <cctype>
#include <cmath>
#include <cstring>
using namespace std;
struct IP
{
int ten[4];//保存十进制形式
char two[4][8];//保存二进制形式,用char类型只是为了省空间
};
bool isbigger(IP a, IP b)//定义IP大于的比较规则
{
int i;
for(i=0; i<4; i++)
{
if(a.ten[i]>b.ten[i])
{
return true;
}
else if(a.ten[i]<b.ten[i])
{
return false;
}
}
return false;
}
bool issmaller(IP a, IP b)//定义IP小于的比较规则
{
int i;
for(i=0; i<4; i++)
{
if(a.ten[i]<b.ten[i])
{
return true;
}
else if(a.ten[i]>b.ten[i])
{
return false;
}
}
return false;
}
void change(IP &a)//将十进制转换为二进制
{
int i, j, temp;
memset(a.two, 0, sizeof(a.two));
for(i=0; i<4; i++)
{
temp = a.ten[i];
for(j=7; j>=0; j--)
{
if(temp==0)
{
break;
}
a.two[i][j] = temp % 2;
temp /= 2;
}
}
}
void rechange(IP &a)//将二进制转换为十进制
{
memset(a.ten, 0, sizeof(a.ten));
int i, j;
for(i=0; i<4; i++)
{
for(j=0; j<8; j++)
{
a.ten[i] *= 2;
a.ten[i] += a.two[i][j];
}
}
}
void check(IP &minn, IP &maxx)//比对处理函数
{
int i, j;
bool t=false;
for(i=0; i<4; i++)
{
for(j=0; j<8; j++)
{
if(t)
{
minn.two[i][j] = 0;
maxx.two[i][j] = 0;
}
else
{
if(minn.two[i][j]!=maxx.two[i][j])
{
t = true;
minn.two[i][j] = 0;
maxx.two[i][j] = 0;
}
else
{
maxx.two[i][j] = 1;
}
}
}
}
}
void print(IP a)
{
int i,j;
printf("%d.%d.%d.%d\n", a.ten[0], a.ten[1], a.ten[2], a.ten[3]);
}
int main()
{
IP temp, maxx, minn;
int i, j, n;
while(scanf("%d", &n)!=EOF)
{
for(i=0; i<n; i++)
{
for(j=0; j<4; j++)
{
scanf("%d%*c", &temp.ten[j]);
}
if(i==0)
{
maxx = temp;
minn = temp;
}
else
{
if(isbigger(temp, maxx))
{
maxx = temp;
}
if(issmaller(temp, minn))
{
minn = temp;
}
}
}
change(minn);
change(maxx);
check(minn, maxx);
rechange(minn);
rechange(maxx);
print(minn);
print(maxx);
}
return 0;
}