题目链接:这里
题意:给出n个IPv4的子网地址,格式是a-b-c-d/l,a b c d l都是十进制数,然后l是网络地址的长度,最长到32,要求输出最低限度的所有的未能划分出的子网地址,这些子网和给出的n个子网没有交集,这些地址和给出的n个地址能组成完整的网络地址。
解法:把所有的ip地址***字典树,并且标记单词节点,之后然后暴力递归找所有未被包含在已有子网里的子网地址。其实就是trie树上暴力。。。。不过题意看pdf看了超久,还是在网上的解题报告弄清题意的,读题需要训练了。
//LA 7043
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010;
struct Trie{
struct node{
int a, b, c, d, l;
node(){}
node(int a, int b, int c, int d, int l) : a(a), b(b), c(c), d(d), l(l) {}
};
int n, cnt, ans[40];
char s[40];
vector <node> v;
int root, sz, ch[maxn][2], flag[maxn];
void get(int x){
for(int i = 7; i >= 0; i--){
if((x>>i)&1) s[cnt++] = '1';
else s[cnt++] = '0';
}
}
void init(){
root = 0;
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
v.clear();
}
void insert(char *s, int len){
int u = root;
for(int i = 0; i < len; i++){
int now = s[i] - '0';
if(!ch[u][now]){
memset(ch[sz], 0, sizeof(ch[sz]));
flag[sz] = 0;
ch[u][now] = sz++;
}
u = ch[u][now];
}
flag[u] = 1;
}
void query(int u, int cur){
if(flag[u]) return;
for(int j = 1; j >= 0; j--){
ans[cur] = j;
if(ch[u][j]){
query(ch[u][j], cur+1);
}
else{
int a, b, c, d;
int tt, l, r;
tt = 0, l = 0, r = 7;
for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
a = tt;
tt = 0, l = 8, r = 15;
for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
b = tt;
tt = 0, l = 16, r = 23;
for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
c = tt;
tt = 0, l = 24, r = 31;
for(int i = l; i <= r; i++) tt = tt * 2 + ans[i];
d = tt;
v.push_back(node(a, b, c, d, cur));
}
}
}
void run(){
int T, ks = 0;
scanf("%d", &T);
while(T--){
init();
scanf("%d", &n);
printf("Case #%d:\n", ++ks);
if(n == 0){
printf("1\n");
printf("0.0.0.0/0\n");
}
else{
for(int i = 0; i < n; i++){
int a, b, c, d, l;
scanf("%d.%d.%d.%d/%d", &a, &b, &c, &d, &l);
cnt = 0;
get(a), get(b), get(c), get(d);
s[cnt] = 0;
insert(s, l);
}
query(0, 0);
cout << v.size() << endl;
for(int i = 0; i < (int)v.size(); i++){
printf("%d.%d.%d.%d/%d\n", v[i].a, v[i].b, v[i].c, v[i].d, v[i].l + 1);
}
}
}
}
}ac;
int main()
{
ac.run();
return 0;
}