算法竞赛入门经典(第二版)-刘汝佳-第四章 函数与递归 互联网协议网络Uva1590

Description

Download as PDF

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$ \le$n$ \le$32 . Network mask always has 32 - 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$ \le$m$ \le$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


在所有ip二进制中从左往右找,找到第一个二进制数不同的地方,任意一个ip从该处开始后面全部改0就得到最小ip,然后从最小ip从该位的前一位开始全改1就得到了子网掩码。


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>


int change(char s[9])        //二进制转十进制
{
    int i,sum=0;
    for(i=7;i>=0;i--)
    {
        sum=sum+(s[i]-'0')*pow(2,7-i);
    }
    return sum;
}

void getip(char ip[33],int flag,char ipmin[])   //得到最小ip二进制型
{
    int i;
    for(i=flag;i<32;i++)
        ip[i]='0';
        strcpy(ipmin,ip);
}
void getzw(char ip[33],int flag,char zw[])      //得到子网掩码二进制型
{
    int i;
    for(i=flag-1;i>=0;i--)
        ip[i]='1';
        strcpy(zw,ip);
}
void cut1(char s1[],char s2[])
{
    int i;
    for(i=0;i<=7;i++)
    s1[i]=s2[i];
}
void cut2(char s1[],char s2[])
{
    int i;
    for(i=8;i<=15;i++)
    s1[i-8]=s2[i];
}
void cut3(char s1[],char s2[])
{
    int i;
    for(i=16;i<=23;i++)
    s1[i-16]=s2[i];
}
void cut4(char s1[],char s2[])
{
    int i;
    for(i=24;i<=31;i++)
    s1[i-24]=s2[i];
}
void My_itoa(int a,char s[])
{
    int i,p;
    for(i=7;i>=0;i--)
    {
        s[i]=(a%2+'0');
        a=a/2;
    }
}
int main()
{
    //freopen("c:\\test.txt","r",stdin);
    //freopen("c:\\hu.txt","w",stdout);
    char t,ip[1005][33]={},temp[9]={},temp2[9]={},temp3[9]={},temp4[9]={},ipmin[33]={},zw[33]={};
    int n,a,b,c,d,i,j,flag=-1,k;
    while(scanf("%d",&n)!=EOF)
    {


    k=n;
    while(n--)
    {
        scanf("%d%c%d%c%d%c%d",&a,&t,&b,&t,&c,&t,&d);
        My_itoa(a,ip[n]);                   //将十进制转成二进制
        My_itoa(b,temp);
        sprintf(temp2,"%08s",temp);
        strcat(ip[n],temp2);
        My_itoa(c,temp);
        sprintf(temp2,"%8s",temp);
        strcat(ip[n],temp2);
        My_itoa(d,temp);
        sprintf(temp2,"%8s",temp);
        strcat(ip[n],temp2);
    }
    for(i=0;i<32;i++)                 //从头开始找二进制中第一个不同的位置
    {
        for(j=1;j<k;j++)
        {

            if(ip[0][i]!=ip[j][i])
            {
                flag=i;
                break;
            }
        }
        if(flag!=-1)
            break;
    }
    if(flag==-1)              //遇到所有ip相同的时候flag为32,则后序不会被替换
    flag=32;
    memset(temp,0,sizeof(temp));   //初始化清零
    memset(temp2,0,sizeof(temp2));
    memset(temp3,0,sizeof(temp3));
    memset(temp4,0,sizeof(temp4));
    getip(ip[0],flag,ipmin);
    getzw(ip[0],flag,zw);
    cut1(temp,ipmin);               //将二进制8个一组分成4组
    cut2(temp2,ipmin);
    cut3(temp3,ipmin);
    cut4(temp4,ipmin);
    printf("%d.%d.%d.%d\n",change(temp),change(temp2),change(temp3),change(temp4));
    cut1(temp,zw);
    cut2(temp2,zw);
    cut3(temp3,zw);
    cut4(temp4,zw);
    printf("%d.%d.%d.%d\n",change(temp),change(temp2),change(temp3),change(temp4));
    flag=-1;
    for(i=0;i<1000;i++)
    {
        memset(ip[i],0,sizeof(ip[i]));
    }
    }
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值