CCF 2018-12-3 CIDR merged 100 points

Insert picture description here

Title

Can correctly read n total of 3 types (standard type, omit suffix type, omit length type) ip address list. It is difficult
for you to simplify the
solution to the prefix list with the smallest number of equivalent IPs . Fortunately, it has been given, just follow Prompt 3 steps

Ideas

Use the following method to save the ip address table

  • In the second step, the third step is to delete the intermediate entry, using list is convenient and efficient
  • The pair defines <priority is frist, second we directly put ip in first length and second in second to meet the meaning of the question
  • unsinged int occupies 32 bits, which is exactly the length of the ip address, and the extracted value depends on the shift operation
list<pair<unsigned int, unsigned int>>iplist;

Follow the prompts on the back

Code



#include <iostream>
#include <list>
#include <string>
#include <fstream>
#include <sstream>
#include <algorithm>
using namespace std;
list<pair<unsigned int, unsigned int>>iplist;
//#define DEBUG
void input() {
#ifdef DEBUG
	fstream cin("input.txt");
#endif
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n;
	cin >> n;
	cin.get();
	while (n--)
	{
		unsigned int  ip = 0, pre;
		string temp;
		getline(cin, temp);
		stringstream strs;
		strs << temp;
		int point = count(temp.begin(), temp.end(), '.');
		for (int i = 0; i < point + 1; ++i) {
			ip <<= 8;
			int tip;
			strs >> tip;
			strs.get();
			ip += tip;
		}
		for (int i = 0; i < 3 - point; i++)ip <<= 8;
		if (temp.find('/') != string::npos) {//省略后缀和标准
			strs >> pre;
		}
		else {//省略长度
			pre = (point + 1) * 8;
		}
		iplist.push_back({ ip, pre });
	}
	iplist.sort();//pair中已经定义了<小于优先级为先比较first再比较second
	//处理好3种输入和排序已经60分了
}

void fun() {
	for (auto i = iplist.begin(), j = ++iplist.begin(); j != iplist.end(); ) {//从小到大合并 80分
		if (i->second <= j->second &&
			i->first >> (32 - i->second) == j->first >> (32 - i->second))
		{
			j = iplist.erase(j);
		}
		else {
			++i; ++j;
		}
	}

	for (auto i = iplist.begin(), j = ++iplist.begin(); j != iplist.end();) {//同级合并100分
		if (i->second != 0 &&//a次合法长度必须大于0才能减,其实后面想也没必要长度为0早就被上面合并为一个了进不来这
			i->second == j->second &&
			((i->first >> (32 - i->second)) ^ (j->first >> (32 - i->second))) == 1)//只有最后一位不同
		{
			--(i->second);
			j = iplist.erase(j);
			if (i != iplist.begin()) {//提示中要求往前跳
				--i; --j;
			}
		}
		else {
			++i; ++j;
		}
	}
}

int main()
{
	input();
	fun();
	for (auto x : iplist) {
		for (int i = 0; i < 4; ++i, x.first <<= 8) {
			cout << (x.first  >> 24);
			if (i != 3)cout << '.';
		}
		cout << '/' << x.second << endl;
	}
}


Homemade test data

4
6
7.0.0.0/8
4.0.0/8
4.0/7
能测试提示中的3个步骤
答案4.0.0.0/6
Published 9 original articles · praised 7 · visits 551

Guess you like

Origin blog.csdn.net/qq_41433566/article/details/105524023