CCF 2018-12-3 CIDR合并 100分

试题编号:201812-3
试题名称:CIDR合并
时间限制:1.0s
内存限制:512.0MB
问题描述:

 

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

typedef struct Node{
	int len;//len要写在long long的前面
	int ip[4];//ip 0,1,2,3 表示IP的1,2,3,4段
	long long val;//IP的十进制数 
}Node;
 
int getNum(string s){//字符串转化为数字 
    int sum=0;
    for(int i=0;i<s.size();i++){
        sum+=(s[i]-'0')*pow(10,s.size()-i-1);
    }
    return sum;
}

Node node[100105];int n;
int deal_input(int no,string s){//解析IP 
	int i=0,dotNum=0;
	while(1){
		if(i>=s.size())break;
		if(s[i]=='/')break;
		if(s[i]=='.')dotNum++;
		i++;
	}
	string ip;int len;
	ip=s.substr(0,i);
	if(dotNum==0){
		ip+=".0.0.0";
	}else if(dotNum==1){
		ip+=".0.0";
	}else if(dotNum==2){
		ip+=".0";
	}
	if(i>=s.size()){
		if(dotNum==0)len=8;
		else if(dotNum==1)len=16;
		else if(dotNum==2)len=24;
		else len=32;
	}else len=getNum(s.substr(i+1,s.size()-i-1));
	Node temp;int a=0,b=0,c=3,x,t=0;
	temp.len=len;
	while(b<ip.size()){
		if(ip[b]=='.'){
			x=getNum(ip.substr(a,b-a));
			temp.ip[t++]=x;
			temp.val+=x*pow(256,c--);
			a=b+1;
		}b++;
	}
	x=getNum(ip.substr(a,b-a));
	temp.ip[t++]=x;
	temp.val+=x*pow(256,c--);
	node[no]=temp;
}

bool cmp(Node a,Node b){//排序 
	if(a.val!=b.val)return a.val<b.val;
	return a.len<b.len;
}

int deal_del_1(){//第一次消除,消除子集 ,消除次数较多,不能采用循环中退步的方式
	int p=0;
    for(int i=1;i<n;i++){
		Node first=node[p],second=node[i];
		if(!((first.val>>(32-first.len))==second.val>>(32-first.len))){
			node[++p]=node[i];//注意消除算法,其中这次消除占大部分时间,消除算法很重要 
		}
	}
	n=p+1;
}


bool judge_del(Node ip1, Node ip2, Node &temp){ //判断同级能否合并 
	if(ip1.len!=ip2.len) return false;
	temp=ip1; temp.len-=1;
	if(temp.val>>(32-temp.len)<<(32-temp.len)==ip2.val>>(32-ip2.len+1)<<(32-ip2.len+1)) return true;
	return false;
}

int deal_del_2(){//第二次消除 ,所占时间较少,可采用循环中退步的消除方式
	int p=0;
	Node temp;
	for(int i=1;i<n;i++){
		if(judge_del(node[p],node[i],temp)){
			node[p]=temp;
			while(p>0 && judge_del(node[p-1], node[p], temp)) node[--p]=temp;
		}
		else node[++p]=node[i];
	}
	n=p+1;
}

int main(){
    string s;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>s;
		deal_input(i,s);
	}
	sort(node,node+n,cmp);
	deal_del_1();
	deal_del_2();
	for(int i=0;i<n;i++){
		cout<<node[i].ip[0]<<"."<<node[i].ip[1]<<"."<<node[i].ip[2]<<"."<<node[i].ip[3]<<"/"<<node[i].len<<endl;
	}
} 

更多相关CCF的试题解答,请点击>>CCF历年认证考试解答

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值