ACM IP NetWorks

来源:互联网 发布:七政四余排盘软件下载 编辑:程序博客网 时间:2024/05/29 18:01

接到训练题后翻了一遍,第一眼就瞅上这个题了,IP地址,之前培训过几天计算机网络知识,知道子网的划分方法。做题之前首先要了解到什么是子网掩码,子网掩码是子网划分的依据,它跟IP地址一样,长度也是32位,点分十进制表示,每部分0~255,但是跟IP地址不同的是,子网掩码只能由连续的1和0组成,也就是说,把这32位从任意位置分开,左边只能全是1,右边只能全是0。比如11111111.11111111.11111111.11111000(255.255.255.248)就是合法的子网掩码,而11000000.10101000.00000001.00000000(192.168.1.0)就不合法(可以尝试一下在计算机上给网络连接手动分配子网掩码,看看它会怎么提示你)。给定两个IP,假设其子网掩码二进制有x个连续的1,则如果这两个IP的二进制前x位对应相等,那么这两个IP就属于同一网段,也就是属于同一个子网。

如果给定一个子网掩码和一个IP,就可以求出这个IP所在子网的最小IP,方法是将IP的二进制与子网掩码的二进制进行按位与运算,原理是,子网掩码为1的二进制位,要求子网内所有IP的这一位必须全部相等,而子网掩码为0的位不作要求,也就是说,给定一个IP,子网内最小IP对应的子网掩码为1的位必须跟给定IP一样,按位与的时候,给定IP与子网掩码是1的位按位与后的结果不变,子网掩码0的位按位与后为0(恰好是最小),这样按位与运算结束后,得到的IP就是子网内最小IP(说的我自己都有点晕乎了,想弄明白这个,必须了解位运算和子网掩码的相关知识)。

说了这么多,都只是预备知识,下面可以切入正题,给定一些IP地址,求出子网掩码和子网内最小IP。

根据上面所说,这个题只要求出子网掩码,然后与给定的任意IP进行按位与运算,就可以得到最小IP了。那么现在关键就是求子网掩码了,既然给定的这一些IP都是一个网段的,那么找到这些IP里的最小IP和最大IP,然后找到这两个IP的二进制从左往右看哪一位最先出现不同(异或运算可解),就可以知道子网掩码里有几个连续的1,自然就得到子网掩码了,然后最小IP便迎刃而解。所以这个题其实很简单,只要了解点IP地址相关知识即可。

实现方面,写了个ip类,有四部分,分别对应点分十进制的四部分,重载<运算符,sort排序后找到给定IP里的最大和最小,这两个IP每部分依次异或运算得到子网掩码连续的1的个数,得到子网掩码,与任意IP按位与,得到最小IP,个人认为这题的精华是位运算的应用,代码如下:

//上面的为摘抄写得很好

代码自己写到最简化

#include<stdio.h>

#include<stdlib.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define MAX 64
using namespace std;
int n;
int buf1[MAX][MAX];
void changetow(int x,int y,int *sum,int *sum2)
{
if (x == y)//如果两个相同直接返回
{
*sum = x;
*sum2 = 255;
return;
}
for (int i = 0;i < 8;i++)
{
//进行按位运算
*sum += ((x % 2) & (y % 2))* (int)pow(2, i);
*sum2 += (!(x % 2) ^ (y % 2))*(int)pow(2, i);
if((x % 2) ^ (y % 2))
{
*sum = 0;
*sum2= 0;
}
x/= 2;
y/= 2;
}
}
int main()
{
freopen("data.in", "r", stdin);
memset(buf1, 0, MAX);
while (scanf("%d", &n) != EOF)
{
for (int i = 0;i < n;i++) {
scanf("%d.%d.%d.%d", &buf1[i][0], &buf1[i][1], &buf1[i][2], &buf1[i][3]);
buf1[n][i] = buf1[i][0];buf1[n+1][i] = buf1[i][1];buf1[n+2][i] = buf1[i][2];buf1[n+3][i] = buf1[i][3];
}
for (int i = 0;i < 4;i++)
{
sort(buf1[n + i], buf1[n + i] + n);//进行排序找出最大和最小
changetow(buf1[n+i][0], buf1[n+i][n-1], &buf1[n + 4][i],&buf1[n + 5][i]);
   }
printf("%d.%d.%d.%d\n", buf1[n+4][0], buf1[n+4][1], buf1[n+4][2], buf1[n+4][3]);
printf("%d.%d.%d.%d\n", buf1[n+5][0], buf1[n+5][1], buf1[n+5][2], buf1[n+5][3]);
}
return 0;
}
原创粉丝点击