天大夏令营题目——IP地址转化(uva1590)

原英文题目.

题目翻译(取自洛谷):

亚历克斯是IP网络的管理员。他的客户每个人有一组单独的IP地址,他决定将所有IP地址分组到最小可能的IP网络中。

每个IP地址有四个部分组成,每个部分用小数点分离。格式如a,b,c,d每个部分都是一个十进制的数(0≤这个数≤255)且没有多余的前导零。

IP网络由两个4各部分的数字——网络地址和网络掩码组成。网络地址和网络掩码和IP地址写入方式相同。为了理解网络地址和网络掩码的含义,我们将它们用二进制来表述。IP地址、网络地址和网络掩码的二进制都由32位组成:a的8位(从最重要到最不重要),其次是b的8位,其次是c的8位,其次是d的8位。

IP网络包含一个2n个IP地址的范围,其中所有n>32。网络掩码始终存在32~n个第一部分设置为一,n个最后部分在二进制表示中设置为零。网络地址已任意32个n个第一部分,n个最后部分在其二进制表示中设置为零。IP网络所有的32个n位第一位相当于32位n个任意位的网络地址的所有IP地址最后一位。

我们说,一个IP网络比其他IP网络更小,那么它包含更少的IP地址。

输入输出格式
输入格式:

有多个测试数据。

输入文件的第一行包含一个整数m。下面m行都是一个IP地址。IP地址可能重复。

输出格式:

每个测试数据在第一行写上网络地址,在第二行写上网络掩码。 网络地址和网络掩码代表的IP网络包括所有IP地址且最小。

样例输入输出:
样例输入#1

3

194.85.160.177

194.85.160.183

194.85.160.178

样例输出#1

194.85.160.176

255.255.255.248

样例说明
一个IP网络的网络地址是194.85.160.176它的网络掩码是255.255.255.248

那么这个IP网络包含8个IP地址从194.85.160.176到194.85.160.183

说明
0 ≤ n ≤ 32,1 ≤ m ≤ 1000

解题重点思路

1、确定n(全为0的位数)
2、10进制ip转2进制ip的函数
3、2进制ip转10进制ip的函数
4、第1点需要利用第2点在2进制下将所有ip进行比较。
5、实践自顶向下的实现模拟

代码(问题必回答):

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
using namespace std;
/******************************************************
IP地址
天大夏令营题目
*******************************************************/
typedef struct
{
    int ip4[4];
}Ip;
Ip Ips[1010];
int binary[33];//存储二进制
int m;
void print_ip(Ip ip)
{
    printf("%d.%d.%d.%d\n",ip.ip4[0],ip.ip4[1],ip.ip4[2],ip.ip4[3]);
}
void print_b()
{
    for(int i=1;i<=32;i++)
    {
        if(i%8==0)
            printf("%d|",binary[i]);
        else
            printf("%d",binary[i]);
    }
    printf("\n");
}
Ip get_10ip()
{
    Ip newip;
    for(int i=0;i<4;i++)
    {
        int tmp = 0,b=1;
        for(int j=(i+1)*8;j>=1+8*i;j--)
        {
            tmp+=binary[j]*b;
            b*=2;
        }
        newip.ip4[i]=tmp;
    }
    return newip;
}
void get_2ip(Ip ip)
{
    memset(binary,0,sizeof(binary));
    for(int i=0;i<4;i++)
    {
        int tmp = ip.ip4[i];
        for(int j=(i+1)*8;tmp>0;j--)
        {
            binary[j]=tmp%2;
            tmp/=2;
        }
    }
}
int get_n(int i)//获取不相同的位数n
{
    int nn;
    bool flag=true;
    for(int n=i*8+1;flag&&n<=32;n++)
    {
        get_2ip(Ips[0]);
        //print_b();
        int x=binary[n];
        for(int j=1;j<m;j++)
        {
            get_2ip(Ips[j]);
            if(x!=binary[n])
            {
                nn=n;
                flag=false;
                break;
            }
        }
    }
    return 32-nn+1;
}
int main()
{
    while(scanf("%d",&m)!=EOF)
    {
        for(int i=0;i<m;i++)
        {
            char left;
            scanf("%d%c%d%c%d%c%d",&Ips[i].ip4[0],&left,&Ips[i].ip4[1],&left,&Ips[i].ip4[2],&left,&Ips[i].ip4[3]);
            getchar();//读取多余回车
        }
        int di;//di为十进制下不相同的ip子节位置
        bool flag=true;
        for(int i=0;i<4&&flag;i++)
        {
            int tmp = Ips[0].ip4[i];
            for(int j=1;j<m;j++)
            {
                if(tmp!=Ips[j].ip4[i])
                {
                    di=i;
                    flag=false;
                    break;
                }
            }
        }
        //printf("di is in %d\n",di);
        int n;
        if(flag)//全都相同或者m=1
        {
            n=0;
        }
        else
        {
            n=get_n(di);
        }
        //printf("n is in %d\n",n);
        get_2ip(Ips[0]);
        for(int j=32;j>32-n;j--)
            binary[j]=0;//将相应的位数全部设置为0
        //print_b();
        Ip result1 = get_10ip();
        for(int j=1;j<=32-n;j++)
            binary[j]=1;
        Ip result2 = get_10ip();
        print_ip(result1);
        print_ip(result2);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值