POJ 2788 ipnetworks 计算机网络相关知识

今天刚好考完计算机网络,刚好复习下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,求出这些ip的子网掩码,和在这个子网掩码下的最有效的ip,其实就是最小ip。

注意给的多个ip已是同一网段下,所以有效ip的前面就是这些ip的共同值,后面全是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的二进制从左往右看哪一位最先出现不同(异或运算可解),就可以知道子网掩码里有几个连续的1,自然就得到子网掩码了,然后最小IP便迎刃而解。所以这个题其实很简单,只要了解点IP地址相关知识即可。

#include <bits/stdc++.h>

using namespace std;
const int maxip = (1<<10)+10;
//对应11111111,11111110,11111100,11111000,11110000,....10000000,00000000依次减去2^0,1,2,3
int tmp[10] = {255, 254, 252, 248, 240, 224, 192, 128, 0};
int main() {
    freopen("in.txt","r",stdin);
//    freopen("ip.out","w",stdout);
    int ip[4][maxip];
    int n;
    while(~scanf("%d",&n))
    {
        memset(ip, 0, sizeof(ip));
        int dns[4];
        int  ansip[4];
        for(int i=0; i<n; i++)
            scanf("%d.%d.%d.%d",&ip[0][i], &ip[1][i], &ip[2][i], &ip[3][i]);
        for(int i=0; i<4; i++)
        {
            int dif_cur=0, x, j;

            sort(ip[i], ip[i]+n);
            int Max = ip[i][n-1];
            int Min = ip[i][0];

        //这里可以优化
            for(j=1; j<=8; j++) {
                if(Max%2 != Min%2)
                        dif_cur = j;
                    //从低位向高位移动,在每位判断当前位是否相同
                    Max = Max>>1;
                    Min = Min>>1;
            }
            //求出这一段的子网掩码
            dns[i] = tmp[dif_cur];
            //最小IP
            //由这一段的子网掩码随便对一个ip(反正都是一个网段)与或运算,只有与1得1,与0会得ip原来的数位即0
            //注意子网掩码和最小的ip不同就是ip在这个网段下,即这个网段的前x个数位都是相同的,子网掩码在这前x个都是1
             ansip[i] = dns[i] & ip[i][1];//这个ip是随便的,只要是这一段的就行,即一维是i
        }

        for(int i=0; i<4; i++)
        {
            if(dns[i] != ((1<<8)-1) )
            {
                for(i = i+1; i<4; i++)
                {
                    dns[i] = 0;
                     dns[i] = 0;
                }
                break;
            }
        }
        printf("%d.%d.%d.%d
",ansip[0], ansip[1], ansip[2], ansip[3]);
        printf("%d.%d.%d.%d
", dns[0],  dns[1],  dns[2],  dns[3]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhangmingzhao/p/7256583.html