A题目,根据同学回忆:
1:对0-9用7(8)段数码管显示时的字形码进行排列,使得对序列中相连两个字形码中的任意一个,只 经过以下两种变换方式中的一种就可以得到另外一个,
【1】增加某些显示段(置某些位为0)。【2】减少某些显示段(置某些位为1)。(注,变化的位数不能是0个,假设0亮1灭)
2:计算任意给定两个日期相隔的天数。
3:对一个长字符串,当中有单词(一个或多个字符组成,标点符号也做单词解释),用空格做间隔符,
现要求对该长字符格式化:一行最多只能存N个字符,要求单词不能跨行存。
为了简单起见,这里我限定字形码如下。
unsigned int seg7[N]=
{
0x3f,/*011 1111*/
0x06,/*000 0110*/
0x5b,/*101 1011*/
0x4f,/*100 1111*/
0x66,/*110 0110*/
0x6d ,/*110 1101*/
0x7d,/*111 1101*/
0x07,/*000 0111*/
0x7f,/*111 1111*/
0x6f,/*110 1111*/
};
B 思路,这里我实际动手编了第一个,第2和3题给了思路。
总的来说,第一题考的位操作的特点和递归函数。第2题类似采用linux内核处理时间的方式,类似 a-b=(a-c)-(b-c),当中c是常量,便于编程。第3题用状态机要好。
第一题结果如下:第一个矩阵是转换矩阵T,T[i][j]==1,则i可以转换为j,显然,T具有关于主对角线的对称性和主对角线上全为0的特性。后面是以满足条件的序列
[root@localhost seg8]# ./a.out
0 1 0 0 0 0 0 1 1 0
1 0 0 1 1 0 0 1 1 1
0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 1 1 1
0 1 0 0 0 0 0 0 1 1
0 0 0 0 0 0 1 0 1 1
0 0 0 0 0 1 0 0 1 0
1 1 0 1 0 0 0 0 1 1
1 1 1 1 1 1 1 1 0 1
0 1 0 1 1 1 0 1 1 0
i=0
0 7 3 1 4 9 5 6 8 2
i=1
i=2
2 8 0 7 3 1 4 9 5 6
2 8 3 7 0 1 4 9 5 6
2 8 4 1 0 7 3 9 5 6
2 8 6 5 9 3 7 0 1 4
2 8 6 5 9 4 1 0 7 3
2 8 6 5 9 4 1 3 7 0
i=3
3 7 0 1 4 9 5 6 8 2
i=4
4 1 0 7 3 9 5 6 8 2
i=5
i=6
6 5 9 3 7 0 1 4 8 2
6 5 9 4 1 0 7 3 8 2
6 5 9 4 1 3 7 0 8 2
i=7
i=8
i=9
以下是具体的分析:第一题
(1)获得T(转换矩阵):要判断T[i][j]是否为1,即i能否转换为j,从^(异或)位运算的特点,相异为1,可以得到一个字形掩码m,m=seg7[i]^seg7[j]。假设掩码m中有为1的位k,从i->j或j->i时,需要seg7中对应的k位进行变换:0->1,或1->0.即seg7[i].k ^(1<<k) ==seg7[j].k 。满足条件的转化是i中所有需要转换的位(掩码m中任何为1的位)都要么经过0->1转换,要么经过1->0转化,而不能是一部经过1->0转换,而另外一部分经过0->1转换。对于i->j,这里只需要保证i中需要转换的位的值是全0或全1就行了,也可以只需保证j中需要转换的位全是0或全是1就行,也可以结合i,j,保证i,j 中需要转化的位的值中有一个是等于掩码m就行,即 (seg7[i]&m ==m) || (seg7[j]&m == m).
(2)依次初始化结果数组的第一个元素为0-9,接下来就可以根据转化矩阵T,使得结果数组逐渐生长,直到得到有10个元素的序列(也是退出条件,并且在退出前打印),这里采用递归的方式,效果挺好。
第二题:略
第三题:状态转化图如下(考虑的是字符串个数大于2的情况,c-普通字符,b-空格,f-结束符(‘\0’)):