易错点:
这道题思路题目已给出,但是易错点有点多,列举一些自己遇到的坑:
1.使用vector容器,由于是顺序表,删除插入操作较多,导致运行超时,用list链表可以做到100分,之后补上;已写好(链接: CCF 20181203 CIDR合并–vector排序+list合并)
2.比较排序时一定要是数字比较,而不是字符串比较,后者会出错;
3.同级合并时,一定要判断新合成的前缀是否合法,即后缀是否全部为0;(其实也就是后一位不能是1)
4.完成第一步排序可得60分,完成从小到大吞并可得80分,完成同级合并且不超时的情况下可得100,否则视超时情况。
#include<bits/stdc++.h>
using namespace std;
struct node{
int ip[4];
int len;
};
vector<node> vip;
inline bool cmp(node a,node b){
for(int i=0;i<4;i++){
if(a.ip[i]!=b.ip[i])return a.ip[i]<b.ip[i];
}
return a.len<b.len;
}
inline bool compare(node a,node b){ //比较吞并函数
int piror=8-a.len%8;
int range=pow(2,piror)-1;
int t=a.len/8;
for(int i=0;i<t;i++){
if(a.ip[i]!=b.ip[i])return false;
}
if(b.ip[t]<=a.ip[t]+range){
return true;
}
return false;
}
inline bool combine(node a,node b,node &neo){ //合并函数
if(a.len!=b.len)return false;
neo.len=a.len-1;
for(int i=0;i<4;i++){
neo.ip[i]=a.ip[i];
}
if(compare(neo,a)&&compare(neo,b)){
int piror=8-neo.len%8;
int range=pow(2,piror)/2;
int t=neo.len/8;
int m=pow(2,piror);
if(neo.ip[t]%m!=0)return false ;//判断neo是否合法
for(int i=0;i<t;i++){
if(a.ip[i]!=b.ip[i])return false;
}
if(b.ip[t]==a.ip[t]+range){
return true;
}
return false;
}
}
inline void table(string str){ //制表
node temp;
int p=str.find('/'),i=0;
temp.len=stoi(str.substr(p+1));
str=str.substr(0,p);
while((p=str.find('.'))!=-1){
str[p]=' ';
}
stringstream ss;
string s;
ss<<str;
while(ss>>s){
temp.ip[i++]=stoi(s);
}
vip.push_back(temp);
}
inline void standard(string &str){ //IP标准化
int t=3,flag=1,p;
for(int i=0;i<str.size();i++){
if(str[i]=='.')t--;
if(str[i]=='/')flag=0;
}
if(flag){
int len=(4-t)*8;
str=str+"/"+to_string(len);
}
p=str.find('/');
while(t--){
str.insert(p,".0");
}
}
int main(){
ios::sync_with_stdio(false);
//输入
int n;
cin>>n;
for(int i=0;i<n;i++){
string str;
cin>>str;
//标准化
standard(str);
//制表
table(str);
}
//排序
sort(vip.begin(),vip.end(),cmp);
//从小到大吞并
for(int i=0;i<vip.size();i++){
if(i+1==vip.size())break;
if(compare(vip[i],vip[i+1])){
vip.erase(vip.begin()+i+1);
i--;
}
}
//同级合并
for(int i=0;i<vip.size();i++){
if(i+1==vip.size())break;
node neo;
if(combine(vip[i],vip[i+1],neo)){
vip.erase(vip.begin()+i,vip.begin()+i+2);
vip.insert(vip.begin()+i,neo);
if(i==0)i--;
else i=i-2;
}
}
//输出
for(auto it:vip){
for(int i=0;i<4;i++){
cout<<it.ip[i];
if(i<3)cout<<'.';
}
cout<<'/'<<it.len<<endl;
}
return 0;
}
样例:
建议全部都要试一遍,否则很难保证算法正确性。
2
2.0.0.0/7
4.0.0.0/7
2
1.0.0.0/8
2.0.0.0/8
2
1.0.0.0/16
2.0.0.0/16
2
10/9
10.128/9
2
0/1
128/1
2
101.128.0.0/10
101.192.0.0/10
2
101.6.6.0/24
101.6.7.0/24
2
101.6.6.0/24
101.6.6.128/25