算法竞赛入门经典 第二版 习题4-5 IP网络 IP Networks uva1590

题目:https://vjudge.net/problem/UVA-1590

听说这题用位运算能大幅简化,奈何我不会用。

思路:既然要找个最小范围,自然要知道上限下限,找出最大的ip和最小的ip,然后转换成二进制,比对这两个ip的二进制,找出第一个不相同的位置。在这个位置之前的二进制位最小的不变,最大的赋值为1;在这个位置之后的每个二进制位(包括这个位置),将两ip都赋值为0。再将处理后的这两个ip转换回十进制。那么原来最小的ip就成了网络地址(network address),原来最大的ip就成了子网掩码(network mask)。

语言:c++

#include <cstdio>
#include <iostream>
#include <cctype>
#include <cmath>
#include <cstring>
using namespace std;
struct IP
{
    int ten[4];//保存十进制形式
    char two[4][8];//保存二进制形式,用char类型只是为了省空间
};
bool isbigger(IP a, IP b)//定义IP大于的比较规则
{
    int i;
    for(i=0; i<4; i++)
    {
        if(a.ten[i]>b.ten[i])
        {
            return true;
        }
        else if(a.ten[i]<b.ten[i])
        {
            return false;
        }
    }
    return false;
}
bool issmaller(IP a, IP b)//定义IP小于的比较规则
{
    int i;
    for(i=0; i<4; i++)
    {
        if(a.ten[i]<b.ten[i])
        {
            return true;
        }
        else if(a.ten[i]>b.ten[i])
        {
            return false;
        }
    }
    return false;
}
void change(IP &a)//将十进制转换为二进制
{
    int i, j, temp;
    memset(a.two, 0, sizeof(a.two));
    for(i=0; i<4; i++)
    {
        temp = a.ten[i];
        for(j=7; j>=0; j--)
        {
            if(temp==0)
            {
                break;
            }
            a.two[i][j] = temp % 2;
            temp /= 2;
        }
    }
}
void rechange(IP &a)//将二进制转换为十进制
{
    memset(a.ten, 0, sizeof(a.ten));
    int i, j;
    for(i=0; i<4; i++)
    {
        for(j=0; j<8; j++)
        {
            a.ten[i] *= 2;
            a.ten[i] += a.two[i][j];
        }
    }
}
void check(IP &minn, IP &maxx)//比对处理函数
{
    int i, j;
    bool t=false;
    for(i=0; i<4; i++)
    {
        for(j=0; j<8; j++)
        {
            if(t)
            {
                minn.two[i][j] = 0;
                maxx.two[i][j] = 0;
            }
            else
            {
                if(minn.two[i][j]!=maxx.two[i][j])
                {
                    t = true;
                    minn.two[i][j] = 0;
                    maxx.two[i][j] = 0;
                }
                else
                {
                    maxx.two[i][j] = 1;
                }
            }
        }
    }
}
void print(IP a)
{
    int i,j;
    printf("%d.%d.%d.%d\n", a.ten[0], a.ten[1], a.ten[2], a.ten[3]);
}
int main()
{
    IP temp, maxx, minn;
    int i, j, n;
    while(scanf("%d", &n)!=EOF)
    {
        for(i=0; i<n; i++)
        {
            for(j=0; j<4; j++)
            {
                scanf("%d%*c", &temp.ten[j]);
            }
            if(i==0)
            {
                maxx = temp;
                minn = temp;
            }
            else
            {
                if(isbigger(temp, maxx))
                {
                    maxx = temp;
                }
                if(issmaller(temp, minn))
                {
                    minn = temp;
                }
            }
        }
        change(minn);
        change(maxx);
        check(minn, maxx);
        rechange(minn);
        rechange(maxx);
        print(minn);
        print(maxx);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值