CCF-CSP 201812-3 CIDR合并【模拟】(100分)

试题编号: 201812-3
试题名称: CIDR合并
时间限制: 1.0s
内存限制: 512.0MB
问题描述:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
样例输入
2
1
2

样例输出
1.0.0.0/8
2.0.0.0/8

样例输入
2
10/9
10.128/9

样例输出
10.0.0.0/8

样例输入
2
0/1
128/1

样例输出
0.0.0.0/0
在这里插入图片描述
本来以为最后一个点会TLE,没想到测试数据这么弱,这都能100分

代码如下(100分):

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
static const int MAXN=100000;
struct Node{
    unsigned int num;
    int len;
    int bit[35];
    bool f;
}ip[MAXN+10],newip[MAXN+10];
int cnt=0;
void div(char s[])
{
    cnt++;
    ip[cnt].len=-1;
    ip[cnt].f=true;
    int p=0,len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int x=0;
        while(i<len && s[i]!='.' && s[i]!='/')
        {
            x=x*10+s[i]-'0';
            i++;
        }
        ip[cnt].num+=x*pow(256,3-p);
        for(int j=p*8+7;j>=p*8;j--)
        {
            ip[cnt].bit[j]=x%2;
            x/=2;
        }
        if(s[i]=='/')
        {
            int y=0;
            while(++i<len)
                y=y*10+s[i]-'0';
            ip[cnt].len=y;
            return;
        }
        p++;
    }
    return;
}
bool cmp(Node P,Node Q)
{
    if(P.num==Q.num)
        return P.len<Q.len;
    return P.num<Q.num;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    int n;
    char s[20];
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        div(s);
        if(ip[cnt].len==-1)
        {
            int pointnum=0;
            for(int j=0;s[j];j++)
                if(s[j]=='.')
                    pointnum+=1;
            ip[cnt].len=pointnum*8+8;
        }
    }
    sort(ip+1,ip+n+1,cmp);
    int p=1;
    newip[1]=ip[1];
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<newip[p].len;j++)
        {
            if(ip[i].bit[j]==newip[p].bit[j])
                continue;
            else
            {
                newip[++p]=ip[i];
                break;
            }
        }
    }
    while(1)
    {

        bool flag=false;
        int pp;
        for(int i=1;i<=p;i++)
            if(newip[i].f)
            {
                pp=i;
                break;
            }
        for(int i=pp+1;i<=p;i++)
        {
            
            if(!newip[i].f)
                continue;
            if(newip[i].len==newip[pp].len)
            {
                for(int j=0;j<newip[i].len-1;j++)
                    if(newip[i].bit[j]!=newip[pp].bit[j])
                    {
                        pp=i;
                        break;
                    }
                if(pp!=i)
                {
                    newip[pp].len-=1;
                    newip[i].f=false;
                    flag=true;
                }
            }
            else
                pp=i;
        }
        if(!flag)
            break;
    }
    for(int i=1;i<=p;i++)
    {
        if(!newip[i].f)
            continue;
        unsigned int a,b,c,d;
        a=newip[i].num/(256*256*256); newip[i].num%=256*256*256;
        b=newip[i].num/(256*256);  newip[i].num%=256*256;
        c=newip[i].num/256; newip[i].num%=256;
        d=newip[i].num;
        cout<<a<<"."<<b<<"."<<c<<"."<<d<<"/"<<newip[i].len<<endl;
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值