题目链接:这里 题意:给出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; }