题目链接: B-Shorten IPv6 Address.
题目描述
          
\;\;\;\;\;
给一个
I
P
v
6
IPv6
IPv6 地址,以一个长度为
128
128
128 位的二进制串表示,对这个地址进行化简。化简规则如下:
          
\;\;\;\;\;
将二进制转换为16进制,从前往后,每4位为一个区域,以
"
:
"
":"
":" 分隔;
          
\;\;\;\;\;
每个区域的前导
0
0
0 可以删除;
          
\;\;\;\;\;
若连续两个及以上的区域为0,可将其用
“
:
:
”
“::”
“::” 代替,代替只能使用至多一次。
          
\;\;\;\;\;
求:化简后最短的地址,若存在多个,输出字典序最小的。
          
\;\;\;\;\;
1
≤
T
≤
1000
1\leq T \leq 1000
1≤T≤1000.
思路
      
\;\;\;
又是一场以一人之力对抗…虽然我也很菜,但是还是想吐槽一下不好好干活的队友
      
\;\;\;
首先保证长度最短,有多个长度的连续
0
0
0,肯定选择最长的化简。
      
\;\;\;
多个长度相同的连续
0
0
0,比如
0
:
0
:
0
:
1
:
1
:
0
:
0
:
0
0:0:0:1:1:0:0:0
0:0:0:1:1:0:0:0,根据字典序最小,选择靠后的区域化简。
e
g
:
eg:
eg:
"
0
:
0
:
0
:
1
:
1
:
:
"
<
"
:
:
1
:
1
:
0
:
0
:
0
"
"0:0:0:1:1::" < "::1:1:0:0:0"
"0:0:0:1:1::"<"::1:1:0:0:0".
      
\;\;\;
然而我忽略了一个坑点,那就是,长度相同的连续
0
0
0,首尾和中间的贡献不同。
      
\;\;\;
e
g
:
eg:
eg:
“
0
:
0
:
1
:
0
:
0
:
1
:
0
:
0
”
→
“
0
:
0
:
1
:
0
:
0
:
1
:
:
”
“0:0:1:0:0:1:0:0”\rightarrow “0:0:1:0:0:1::”
“0:0:1:0:0:1:0:0”→“0:0:1:0:0:1::”.
      
\;\;\;
      
\;\;\;
    
\;\;
“
0
:
0
:
1
:
0
:
0
:
1
:
0
:
0
”
→
“
0
:
0
:
1
:
:
1
:
0
:
0
”
“0:0:1:0:0:1:0:0”\rightarrow “0:0:1::1:0:0”
“0:0:1:0:0:1:0:0”→“0:0:1::1:0:0”.
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200;
#define EPS (1e-10)
int b[MAXN], c[MAXN];
int main() {
int T;
int Len3 = 8;
scanf("%d", &T);
for(int tt = 1; tt <= T; tt++) {
for(int i = 1; i <= 8; i++) {
int x = 0, s;
for(int j = 1; j <= 16; j++) {
scanf("%1d",&s);
x = x*2 + s;
}
b[i] = x;
}
for(int i = 1; i <= 10; i++) c[i] = 0; c[0] = 100;
int l = 0;
for(int i = 1; i <= Len3; i++) {
if(b[i] == 0) l++;
else if(l > 0) {
c[l] = i - l;
l = 0;
}
}
if(l > 0 && c[l] <= 1) c[l] = Len3 - l + 1;
bool flag = 0;
printf("Case #%d: ",tt);
for(int i = 8; i >= 2;i--) {
if(c[i] > 0) {
for(int j = 1; j <= 8; j++) {
if(j == c[i]) {
flag = 1;
printf("::");
j = j + i - 1;
}
else {
printf("%x", b[j]);
if(j < 8 && flag || (!flag && (j+1) != c[i])) printf(":");
}
}
printf("\n");
flag = 1;
break;
}
}
if(!flag) {
for(int i = 1; i <= 8; i++) {
printf("%x%c", b[i],":\n"[i==8]); // 优秀的写法,虽然我还不懂
}
}
}
return 0;
}
错误点
           \;\;\;\;\; 字符串模拟题。题解说推荐学习所有提交中最短的几份代码的写法。感觉差距挺大。