参考资料:
[1]:官方题解(提取码:bdv1)
B.Shorten IPv6 Address(模拟)
•题意
已知 ip 地址由 8 位十六进制的数组成;
例如 ip = 0000:0000:0123:4567:89ab:0000:0000:0000;
现在让你按照如下规则化简这个 ip 地址:
(1):前导 0 去掉,例如上述 ip 地址可化简为 ip1 = 0:0:123:4567:89ab:0:0:0;
(2):连续的 0 字段用 ':' 代替,但只能替换一次,例如,在 ip1 的基础上再进行化简;
ip2 = ::0123:4567:89ab:0000:0000:0000 或 ip2 = 0000:0000:0123:4567:89ab::;
(3):再长度最短的情况下使得字典序最小,例如,上述 ip 地址化简中有两个 ip2,取字典序最小的
ip3 = 0000:0000:0123:4567:89ab:: ;
给你 128 位二进制表示的字符串,输出简化后的 ip 地址(转化成十六进制);
•题解
按照题意模拟即可;
我是先将二进制数转化成十进制数进行化简操作,然后输出十六进制的 ip 地址;
需要注意的坑点,假设某化简前的 ip = 0:0:1:0:0:1:0:0;
将中间的两个 0 字段用 ':' 代替比将末尾的两个 0 字段用 ':' 代替长度更短;
所以此 ip 地址化简后的结果位 ip = 0:0:1::1:0:0;
•Code
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INFll 0x3f3f3f3f3f3f3f3f 4 #define ll long long 5 const int maxn=200; 6 7 char s[maxn]; 8 int ip[20]; 9 vector<int >p[20];///p[i]:连续的i个0字段的起始位置 10 char ch[20]="0123456789abcdef"; 11 12 int f(int j)///二进制转十进制 13 { 14 int ans=0; 15 int cnt=0; 16 for(int i=j+15;i >= j;--i) 17 { 18 if(s[i] == '1') 19 ans += (1<<cnt); 20 21 cnt++; 22 } 23 return ans; 24 } 25 void OX(int v)///十进制转十六进制 26 { 27 if(v/16 == 0) 28 { 29 printf("%c",ch[v%16]); 30 return ; 31 } 32 OX(v/16); 33 34 printf("%c",ch[v%16]); 35 } 36 void Solve() 37 { 38 int k=0; 39 for(int i=1;k < 8;i += 16) 40 ip[++k]=f(i); 41 42 for(int i=0;i <= 8;++i) 43 p[i].clear(); 44 45 int index=1; 46 while(index <= k)///查找连续的0位置 47 { 48 for(;index <= k && ip[index] != 0;index++); 49 50 int cnt=0; 51 int cur=index; 52 53 for(;index <= k && ip[index] == 0;cnt++,index++); 54 p[cnt].push_back(cur); 55 } 56 57 for(int i=k;i > 1;--i)///从大到小查找大于两个字段的0位置 58 { 59 if(p[i].size() == 0) 60 continue; 61 62 int cur=p[i][p[i].size()-1]; 63 ///判断cur是否为末尾的连续的0,并且判断中间是否含有相同长度的0字段 64 if(p[i].size() > 1 && cur+i == 9 && p[i][p[i].size()-2] != 1) 65 cur=p[i][p[i].size()-2]; 66 67 for(int j=1;j < cur;++j) 68 { 69 OX(ip[j]); 70 if(j != cur-1) 71 printf(":"); 72 } 73 printf("::"); 74 for(int j=cur+i;j <= k;++j) 75 { 76 OX(ip[j]); 77 if(j != k) 78 printf(":"); 79 } 80 printf("\n"); 81 return ; 82 } 83 84 for(int i=1;i <= k;++i) 85 { 86 OX(ip[i]); 87 if(i != k) 88 printf(":"); 89 } 90 printf("\n"); 91 } 92 93 int main() 94 { 95 //freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin); 96 int T; 97 scanf("%d",&T); 98 for(int kase=1;kase <= T;++kase) 99 { 100 scanf("%s",s+1); 101 102 printf("Case #%d: ",kase); 103 Solve(); 104 } 105 return 0; 106 }