[WUST2017]算法竞赛入门经典第四章 K - IP Networks (与二进制的操作有关)

题目:K - IP Networks
Alex is administrator of IP networks. His clients have a bunch of individual IP addresses and he decided to group all those IP addresses into the smallest possible IP network. Each IP address is a 4-byte number that is written byte-by-byte in a decimal dot-separated notation “byte0.byte1.byte2.byte3” (quotes are added for clarity). Each byte is written as a decimal number from 0 to 255 (inclusive) without extra leading zeroes. IP network is described by two 4-byte numbers — network address and network mask. Both network address and network mask are written in the same notation as IP addresses. In order to understand the meaning of network address and network mask you have to consider their binary representation. Binary representation of IP address, network address, and network mask consists of 32 bits: 8 bits for byte0 (most significant to least significant), followed by 8 bits for byte1, followed by 8 bits for byte2, and followed by 8 bits for byte3. IP network contains a range of 2n IP addresses where 0 ≤ n ≤ 32. Network mask always has32 −n first bits set to one, and n last bits set to zero in its binary representation. Network address has arbitrary 32−n first bits, and n last bits set to zero in its binary representation. IP network contains all IP addresses whose 32−n first bits are equal to 32−n first bits of network address with arbitrary n last bits. We say that one IP network is smaller than the other IP network if it contains fewer IP addresses. For example, IP network with network address 194.85.160.176 and network mask 255.255.255.248 contains 8 IP addresses from 194.85.160.176 to 194.85.160.183 (inclusive).
Input
The input file will contain several test cases, each of them as described below. The first line of the input file contains a single integer number m (1 ≤ m ≤ 1000). The following m lines contain IP addresses, one address on a line. Each IP address may appear more than once in the input file.
Output
For each test case, write to the output file two lines that describe the smallest possible IP network that contains all IP addresses from the input file. Write network address on the first line and network mask on the second line.

Sample Input
3 194.85.160.177 194.85.160.183 194.85.160.178
Sample Output
194.85.160.176 255.255.255.248

题意:先输入一个m表示IP地址的个数,之后再输入m个IP地址,然后根据IP地址的那些性质(这个只能看题翻译一下);输出网络地址和子网掩码;

思路:两种:
第一种:用一个二维数组,用一列4个来一个IP地址的四个数,然后再找到最小的和最大的,然后比较最大和最小对应部分是否相等,不相等的那一行就跳出,将其最大和最小的这两个不相等的数转化成二进制的字符串,然后反向比较,找到有多少位是相等,然后不相等的就变成0,在将其转化成10进制,然后就可以得到网络地址和子网掩码了;(用的是二进制字符串
第二种:前面存的方法和第一种一样,但是不用排序,只需要找第一个,然后将第一个依次与后面对应的比,有不相同的就从这个数开始,然后依次进行位运算右移1位,知道相同,然后讲移动的位数记下来,然后再移回来之后就是相同的了,然后就依次得到网络地址和子网掩码。(用的是位运算将多余不相同的给溢出去,然后再移回来的方法);

教训:一开始一直用的是第二种方法,然后就一直WA,然后就改用了第一种方法,不过后来同学帮忙测数据之后才发现是位运算的左移和加1出现了问题;(所以以后在用位运算的时候,左移右移多少位要特别注意一下!!);

代码
第一种:

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

void change(int *,int );

int main()
{
    int T,i,j,sum,t,x,y;
    int  s[10],ss[10],a[5][1005];
    while(scanf("%d",&T)!=EOF)
    {
        for(i=0;i<T;i++)
            scanf("%d%*c%d%*c%d%*c%d",&a[0][i],&a[1][i],&a[2][i],&a[3][i]);
        for(i=0;i<4;i++)
            sort(a[i],a[i]+T);

        for(i=0;i<4;i++)
        {
            y=a[i][0];
            if(y!=a[i][T-1])
                break;
            a[i][T]=a[i][0];
            a[i][T+1]=255;
        }
        change(s,a[i][0]);
        change(ss,a[i][T-1]);
        a[i][T]=0;
        for(x=7;x>=0;x--)
        {
            if(s[x]!=ss[x])
            break;
            a[i][T]=a[i][T]*2+s[x];
        }
        for(j=x;j>=0;j--)
            a[i][T]<<=1;
        for(j=i+1;j<4;j++)
            a[j][T]=0;
        sum=0;
      //  printf("%d\n",x);
        for(j=7;j>x;j--)
        {
            sum=sum*2+1;
        }
        for(j=x;j>=0;j--)
            sum=sum*2;
        a[i][T+1]=sum;
        for(t=i+1;t<4;t++)
            a[t][T+1]=0;
        printf("%d.%d.%d.%d\n",a[0][T],a[1][T],a[2][T],a[3][T]);
        printf("%d.%d.%d.%d\n",a[0][T+1],a[1][1+T],a[2][T+1],a[3][T+1]);
    }
    return 0;
}

void change(int *s,int t)
{
    int i;
    for(i=0;i<8;i++)
    {
        s[i]=t%2;
        t/=2;
    }
}

第二种(可以再改进):

#include<stdio.h>

int main()
{
   unsigned int T,i,j,a[1005][5],s,ss,tag,num,tum,sum,t,x,y,ttt;
    while(scanf("%u",&T)!=EOF)
    {
        tag=0;
        for(i=0;i<T;i++)
            scanf("%u%*c%u%*c%u%*c%u",&a[i][0],&a[i][1],&a[i][2],&a[i][3]);
        for(i=0;i<4;i++)
        {
            s=a[0][i];
            for(j=1;j<T;j++)
            if(s!=a[j][i])
                {tag=1;break;}
            if(tag)
                break;
            a[T][i]=a[0][i];
            a[T+1][i]=255;
        }
        num=1;
        for(x=(a[0][i]>>1);x>=0;x>>=1)
        {
            ss=1;
            for(y=j;y<T;y++)
                a[y][i]>>=1;
            for(y=j;y<T;y++)
                if(x!=a[y][i])
                {j=y;ss=0;num++;break;}
            if(ss)
                break;
        }
        a[T][i]=x<<num;
        for(j=i+1;j<4;j++)
            a[T][j]=0;
        sum=0;
         for(j=1;j<=8-num;j++)
            {
                sum<<=1;
                sum+=1;
            }
        a[T+1][i]=sum<<num;
        for(t=i+1;t<4;t++)
            a[T+1][t]=0;
        printf("%u.%u.%u.%u\n",a[T][0],a[T][1],a[T][2],a[T][3]);
        printf("%u.%u.%u.%u\n",a[T+1][0],a[T+1][1],a[T+1][2],a[T+1][3]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值