201812-3 CIDR合并

试题编号: 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
在这里插入图片描述

90分 运行超时
可能是将点分十进制转换为二进制字符串形式,最后输出的时候再转为int形式的二进制自己写的函数步骤太多的原因

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
struct IP {
	string ip;
	int len;
};

//将点分十进制转换成标准二进制形式并存入IP结构体
void trans(IP &ip1, string s1) {
	int p1=0, p2, l=0, x, s;
	string st;
	while ((p2 = s1.find('.',p1+1)) >= 0)
	{
		l = l + 8;
		st = s1.substr(p1, p2 - p1);
		x = atoi(st.c_str());
		s = 128;
		while (s > 0)
		{
			if (x / s == 1)
			{
				ip1.ip += '1';
				x %= s;
			}
			else
				ip1.ip += '0';
			s /= 2;
		}
		p1 = p2+1;
	}
	l = l + 8;
	if ((p2 = s1.find('/', 0)) >= 0)
	{
		st = s1.substr(p1, p2 - p1);
		x = atoi(st.c_str());
		s = 128;
		while (s > 0)
		{
			if (x / s == 1)
			{
				ip1.ip += '1';
				x = x%s;
			}
			else
				ip1.ip += '0';
			s /= 2;
		}

		p1 = p2 + 1;
		p2 = s1.length();
		st = s1.substr(p1, p2 - p1);
		ip1.len = stoi(st.c_str());
	}
	else
	{
		p2 = s1.length();
		st = s1.substr(p1, p2 - p1);
		x = atoi(st.c_str());
		s = 128;
		while (s > 0)
		{
			if (x / s == 1)
			{
				ip1.ip += '1';
				x = x%s;
			}
			else
				ip1.ip += '0';
			s /= 2;
		}

		ip1.len = l;
	}
	for (int j = l; j < 32; j++)
	{
		ip1.ip += '0';
	}
	
}
//对IP进行排序,用sort函数             按ip从小到大排,如果相同再按前缀从大到小排序
int comp(const IP &ip1, const IP &ip2) {
	if (ip1.ip == ip2.ip)
		return ip1.len < ip2.len;
	else
		return ip1.ip < ip2.ip;
}

//二进制转十进制
void zhuan(string ss,int &xx){
	xx = atoi(ss.c_str());
	long long int f = 10000000,s=0,ff=128;
	for (int i = 0; i < 8; i++)
	{
		if (xx / f == 1)
			s += ff;
		xx = xx%f;
		ff /= 2;
		f /= 10;
	}
	xx = s;
}

int main() {
	int i, j, n, m, flag, flag1, flag2;
	string s;
	IP ipv[100001];
	cin >> n;
	for (i = 0; i < n; i++)
	{
		cin >> s;
		trans(ipv[i], s);
	}
	sort(ipv, ipv + n , comp);               //头文件需注意 还有自定义函数的用法
	//从小到大合并
	flag = n;
	for (i = 0; i < flag-1; i++)
	{
		flag1 = 0;
		for (j = 0; j < ipv[i].len; j++)             //按前一个的前缀部分来看都相同 说明后者是前者的子集
		{
			if (ipv[i].ip[j] != ipv[i + 1].ip[j])
			{
				flag1 = 1;
				break;
			}
		}
		if (flag1 == 0)
		{
			flag--;
			for (j = i+1; j < flag; j++)
				ipv[j] = ipv[j + 1];
			i--;
		}
	}
	//同级合并
	for (i = 0; i < flag - 1; i++)
	{
		if (ipv[i].len == ipv[i+1].len)
		{
			flag2 = 0;
			for (j = 0; j < ipv[i].len - 1; j++)
			{
				if (ipv[i].ip[j] != ipv[i + 1].ip[j]) {
					flag2 = 1;
					break;
				}
			}
			if (flag2 == 0 && ipv[i].ip[ipv[i].len - 1] == '0'&&ipv[i + 1].ip[ipv[i].len - 1] == '1') {
				ipv[i].len =ipv[i].len- 1;
				for (j = i + 1; j < flag - 1; j++)
					ipv[j] = ipv[j + 1];
				flag--;
				if (i > 0)
					i = i - 2;
				else
					i--;
			}
		}
	}
	for (i = 0; i < flag; i++)
	{
		int p1 = 0; 
		int p2 = 8, f;
		string st;
		while (p2 <= 32)
		{
			st = ipv[i].ip.substr(p1, p2 - p1);
			zhuan(st, f);
			if (p1 != 0)
				cout << ".";
			cout << f;
			p1 = p2;
			p2 += 8;
		}
		cout <<"/" << ipv[i].len << endl;
	}	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值