zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    mysql分表技术(学习心得)
    Linux下搭建DNS服务器
    php简单单例模式
    JQuery的ajaxFileUpload图片上传初试
    Binary Tree Level Order Traversal II
    Remove Element
    Symmetric Tree
    Balanced Binary Tree
    Power of Two
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/7256583.html
Copyright © 2011-2022 走看看