声明:本文章题目来源均为牛客网
链接:https://ac.nowcoder.com/acm/contest/886#question
A-Garbage Classification
一道垃圾分类题(2333),签到就不讲了。
B-Shorten IPv6 Address
题目类型:进制转换,思维模拟
题目链接:https://ac.nowcoder.com/acm/contest/886/B
题目大意
给一个01二进制字符串地址,一共有128个字符,然后确定它的最短表示:
以十六进制表示形式表示地址,并使用冒号 ' : ' 分割每四个十六进制数字。每四个数字称为一个字段,例如:
00000000000000000000000000000000000000010010001101000101011001111000100110101011000000000000000000000000000000000000000000000000
转化为下面的形式(这里的:是中文字符,为了方便演示,写代码的时候注意下中英文)
0000:0000:0123:4567:89ab:0000:0000:0000
可以省略字段中的前导零。例如上面的十六进制表示为:
0:0:123:4567:89ab:0:0:0
由至少两个字段组成的连续零字段(包括靠近它们的冒号)可以用双冒号'::'替换。此外,地址中不能使用多个双冒号。
例如,上面的IPv6地址可以缩短为0:0:123:4567:89ab ::或:: 123:4567:89ab:0:0:0,但不能缩写为:: 123:4567: 89ab ::。
如果有多个相同长度的最短格式,请使用字典(将缩短的IPv6地址视为字符串)最小的一个。
题目理解
二进制转换成十六进制的方法是,取四合一法,所以16个二进制数字可转换为4个十六进制数字,而c语言里有现成的16进制的输出方式(%x),
so,我们可以把128个字符里每16个字符表示的十进制数字用数组存起来,然后输出的时候用%x输出每个数字就行了(转换成数字还可以去掉前导零)。
不过还要考虑题目所说的最短的输出,所以还要考虑连续的数字0的最长长度。而且题目说了相同长度的串要求输出字典序最小的那一个,查一下ASCII表,发现' : '大于' 0 ',所以应该尽量输出最长长度0数字连续子串在中间的字符串或者靠后的。
比如0:0:123:4567:89ab ::或:: 123:4567:89ab:0:0:0应该输出第一个。
题目代码
#include<iostream>
#define sc(x) scanf("%d",&x); //方便输入
using namespace std;
int main(){
int t,x;sc(t);x=t;getchar();
while(t--){
int maxlen=0,len=0,pos=0,a[20];
for(int i=1;i<=8;i++){
a[i]=0;
for(int j=1;j<=16;j++){ //数字转换
int x=getchar()-'0';
a[i]=a[i]*2+x;
}
if(a[i]==0) len++; //连续0的长度
else{
if(len>=maxlen&&len>1){ //更新连续0的最大长度
maxlen=len;
pos=i-len;
}
len=0;
}
if(i==8&&len>1){ //如果中间连续零子串较短就选择靠后的
if(len>maxlen||(len==maxlen&&pos==1)){
pos=i-len+1;
maxlen=len;
}
}
}
// for(int i=1;i<=8;i++) printf("%d\n",a[i]);
printf("Case #%d: ",x-t);
if(pos==1) printf(":");
for(int i=1;i<=8;i++){
if(i==pos) printf(":"),i+=maxlen;
if(i>8) printf("\n");
else printf("%x%c",a[i],":\n"[i==8]);//if(i=8) 输出\n else 输出 :
}
}
return 0;
}
/*
题目样例
3
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000010010001101000101011001111000100110101011000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000010010001100000000000000000000000000000000000000000000000001000101011001111000100110101011
*/
后记
这题题目看懂了就好做了,模拟题一般需要看懂题目。