传送门

 

 参考资料:

  [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

  1 #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 }
View Code

相关文章:

  • 2021-07-26
  • 2021-08-03
  • 2021-12-15
  • 2021-10-27
  • 2022-03-07
  • 2021-08-05
  • 2021-10-29
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-02-24
  • 2022-01-08
  • 2022-02-09
相关资源
相似解决方案