题意:
给你一个二进制表示的IPv6地址,让你把它转换成8组4位的16进制,用冒号分组的表示法。单组的前导0可以省略,连续多组为0的可以用两个冒号替换,但是只允许替换一次。把这个地址通过这几种省略方式,长度缩到最短,然后输出字典序最小的。
题解:
计算出八组四位16进制数的值,找出连续的0,用冒号替换即可。
坑点:1,替换连续的0的时候,一定要注意冒号不能多加
2,题目要求字典序最小,因为冒号的ascii值大于0,那就优先替换后面的,但是,同样长度的连续0,替换掉中间的,比替换掉两边的,最后得到的长度要短1,因此要优先替换掉中间的。
#include<iostream> #include<cstring> #include<string> using namespace std; char ip[2005],fl[30]; int count[26]; int qj[10]; int main(){ // printf("%d",'9'); //0=48 :=58 省略最右边的 // int k; scanf("%d",&k); for(int I=1;I<=k;I++){ scanf("%s",ip); int l=128; // msmset(qj,0,sizeof qj); for(int i=0;i<8;i++){ qj[i]=0; for(int j=0;j<16;j++){ qj[i]<<=1; qj[i]+=ip[i*16+j]-'0'; } } int lx0=0,lx0max=0,lx0over=0; for(int i=7;i>=0;i--){ if(qj[i]==0){ lx0++; if(lx0>lx0max){ lx0over=i; lx0max=lx0; }else if(lx0==lx0max){ if(lx0over+lx0max==8 && i!=0){ lx0over=i; lx0max=lx0; } } }else{ lx0=0; } } printf("Case #%d: ",I); bool alrdy=0; for(int i=0;i<8;i++){ if(lx0max>=2 && lx0over==i){ if(alrdy==0)printf("::"); else printf(":"); alrdy=1; i+=lx0max-1; }else{ printf("%x",qj[i]); alrdy=0; if(i<7){ printf(":"); alrdy=1; } } } printf(" "); } }