芯片测试——枚举与分治

问题描述

有n片芯片,已知好芯片比坏芯片至少多1片。现在需要通过测试从中找出1片好芯片,测试方法如下:将2片芯片放到测试台上,2片芯片互相测试并报告测试结果(即好或者坏);其中,好芯片的报告是正确的,而坏芯片的报告是不可靠的。请在上述背景下解决以下问题:

问题1:若用枚举法从中找出1片好芯片,在最坏的情况下,需要多少测试次数?请给出详细的分析过程;

问题2:相比于枚举法,为保证使用更少的测试次数,请设计一个合适的算法解决上述问题。

算法设计思路

问题一:

若n=1,因为好芯片比坏芯片至少多1,所以该芯片就是好的,此时测试次数为0;

若n=2,同理,只可能是两个芯片都是好的,测试次数为0;

若n>2时:

①n为偶数时至少有n/2+1个好芯片,按照枚举法,每次拿出一个芯片与其他芯片做测试,若该芯片是好芯片,那么至少有n/2个芯片会报告它是好芯片,若该芯片是坏芯片,那么至少有n/2+1个芯片会报告它是坏芯片。

因此,若该芯片是好芯片,那么至少有一半的芯片会报告它是好芯片,否则,它就是坏芯片。

②n为奇数时至少有(n+1)/2个好芯片,按照枚举法,每次拿出一个芯片与其他芯片做测试,若该芯片是好芯片,那么至少有(n-1)/2个芯片会报告它是好芯片,若该芯片是坏芯片,那么至少有(n+1)/2个芯片会报告它是坏芯片。

因此,若该芯片是好芯片,那么至少(n-1)/2的芯片会报告它是好芯片,否则,它就是坏芯片。

问题二:

首先,对于该问题的结果进行分析:

①由问题一可知,当n<=2时,每一个芯片都是好芯片,没必要进行测试,因此测试次数为0

②当n>2时,由题意可知,一开始的好芯片是比坏芯片多的,而每次的相互判断情况有以上四种。

如果n是偶数,将n个芯片两个为一组进行判断,当出现第2、3、4种情况的时候,说明芯片A和B至少有一个是坏芯片,或者都是坏芯片。此时若是将这两个芯片移除出,则剩余的芯片中,好芯片数量还是多于坏芯片的,这样就将问题规模缩小了,若当前状态下,没出现情况2,3,4,即只出现情况1,说明每一对芯片同为好或者同为坏,那么每一对芯片就随意拿掉一个,剩下的好芯片数量还是多于坏芯片数量。

如果n是奇数,那么先对单独一个芯片进行枚举法判断,若判断得出该芯片是好芯片,那么就不用计算下去,若判断得出该芯片是坏芯片,则将它拿掉,再对剩下的芯片进行如上判断。

综上所述,对于n是奇数时,可以对最后一个按照问题一的算法判断,若是好芯片,算法结束,若是坏芯片,则弃掉,剩余芯片个数转化为偶数个;对于n是偶数,将芯片两两一组,有n/2组,若测试结果为情况1,则随意丢弃一块芯片,若测试结果为情况2、3、4,则两块都丢弃,若再次出现奇数块的芯片,则再取出一块做问题一的算法判断,直到剩下两块及以下,则都为好芯片,任取一块即可。

算法实现的伪码

问题一:

函数:seek(all, n)

输入:包含所有芯片的集合all,芯片个数n

输出:确定是好芯片的芯片下标

S1: for i ← 0 to n/2//逐个遍历第0个到第n/2个芯片,直到找到一个好芯片

S2: isTrue ← 0//记录其他芯片对此芯片判断为好的个数

S3: for j ← 0 to n-1

S4: if j!=i//除了第i个的其他芯片

S5: then pd ← judge(all[i], all[j])//返回第j个芯片对第i个芯片的好坏判断(true/false)

S6: if pd == true

S7: then isTrue ← isTrue+1//判断为true,记录个数+1

S8: if isTrue > n/2//判断结果为好的个数超过一半

S9: then return i//返回确定为好芯片的下标i

S10: if isTrue == n/2 and n%2 != 0//奇数个的特殊情况判断

S11: then return i//返回确定为好芯片的下标i

问题二:

函数:does(S, n)

输入:芯片集合S和个数n

输出:找到的好芯片的下标

S1: if n <= 2

S2: then return 0//返回第一块芯片

S3: if n%2 != 0//奇数个

S4: then if test(S, n) == true//判断最后一块芯片是不是好芯片

S5: then return n//n为好芯片,返回

S6: else n ← n-1//个数-1,即舍弃最后一个芯片

S7: nums ← 0//记录一轮判断后的剩余个数

S8: for i from 0 to n-1 step 2//两个两个判断(此时n肯定是偶数)

S9: if pd(S[i], S[i+1]) == true//两芯片结果若是情况1则为true,否则为false

S10: then nums ← nums+1//个数+1

S11: newS[nums-1] ← S[i]//结果为true,任取一个芯片存入新的集合

S12: return does(newS, nums)//将问题规模变为小于等于原来的1/2

算法实现的源码

问题一:

import java.util.Scanner;

public class Main {
   

      public static void main(String[] args) {
   

             Scanner in = new Scanner(System.in);

             //好芯片为true,坏芯片为false

             boolean[] all= {
   false, false, false, false, false, 
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值