芯片测试及其应用(分治典例)

问题叙述:

VLSI芯片测试

Diogenes教授有n个被认为是完全相同的VLSI芯片,原则上它们是可以互相测试的。教授的测试装置一次可测二片,当该装置中放有两片芯片 时,每一片就对另一片作测试并报告其好坏。一个好的芯片总是能够报告另一片的好坏,但一个坏的芯片的结果是不可靠的。这样,每次测试的四种可能结果如下:

 

    A芯片报告         B芯片报告     结论


    B是好的          A是好的      都是好的,或都是坏的

    B是好的          A是坏的      至少一片是坏的

    B是坏的          A是好的      至少一片是坏的

    B是坏的          A是坏的      至少一片是坏的

 

a)证明若多于n/2的芯片是坏的,在这种成对测试方法下,使用任何策略都不能确定哪个芯片是好的。假设坏的芯片可以联合起来欺骗教授。

b)假设有多于n/2的芯片是好的,考虑从n片中找出一片好芯片的问题。证明n/2对测试就足以使问题的规模降至近原来的一半。

c)假设多于n/2片芯片是好的,证明好的芯片可用Θ(n)对测试找出。给出并解答表达式测试次数的递归式。

注:VLSI——Very Large ScaleIntegrated.

算法分析:

a)采用穷举法,将任何一片芯片与其它所有芯片进行比较,因为有多于n/2的芯片是坏的,且坏的芯片可以联合起来欺骗教授,则测试结果是不可靠的,无法判断出该芯片是好是坏。

b)假设:设有a个好的芯片数,b个坏的芯片数,z对测试结果为全好的测试对,其中芯片全为好的测试对为x,芯片全为坏的测试对为y,x+y=z。

二分测试思想:

1.随机的两两配对,则共有⌊n/2⌋对,分别测试。

2.根据问题描述:如果测试结果为一好一坏,或者两坏,那么把这对丢弃;如果测试结果为两好,那么随意丢弃其中一个,留下一个(若n为奇数,则剩余一个芯 片没有配对。若z为奇数,丢弃这个芯片;若z为偶数(0也看做偶数),留下这个芯片)。这样操作后,留下的好芯片数一定还是大于坏的芯片数的,且经过⌊n/2⌋对测试后,原问题的规模降低了近一半。

3.重复第2步,当n<=2时,就只剩下了好的芯片。

证明:

测试结果为一好一坏或者两坏的芯片对中至少一片是坏的,把这对丢弃能保证剩下的芯片中好芯片的数量仍大于坏芯片的数量。

测试结果为全好的,这对芯片有可能全为好,有可能全为坏,随意丢弃其中一个,留下 一个。设好芯片的对数为x,坏芯片的对数为y。考虑n的情况:

      若n为偶数,则x>y,所以留下的好芯片数还是大于坏的芯片数;

      若n为奇数,则剩余一个没有配对的芯片。考虑z的情况:

          若z是奇数,则x>y,丢弃这个芯片,这样留下的好芯片数还是大于坏的芯片数;

          若z是偶数,考虑这个芯片的情况:

               若芯片是好的,则x>=y,留下这个好的芯片,这样留下的好芯片数还是大于坏的芯片数;           

               若芯片是坏的,则x-y>=2,留下这个坏的芯片,这样留下的好芯片数还是大于坏的芯片数。

综上所述,留下的好芯片数一定还是大于坏的芯片数的。

c)采用b中的操作方法,递归式为:f(n) = f(n/2) + n/2。这个递归式符合主定理中的第三种情况,所以好的芯片可用Θ(n)对测试找出。

 

应用:

1.主元素:

何谓主元素?具体讲,如果一个数组A[1..n]中超过半数的元素都相同时,该数组被称为含有一个主元素 (a)设计一个有效算法,确定该数组中是否含有一个主元素,如果有,找出这个元素。(b)能否给出一个线性时间算法?

注意,该数组的元素之间可能不存在顺序——即不能进行”A[i]的大小判断,但是可以进行是否相等的判断。普通的算法即需要2for循环,算出每个数字的个数,这比较简单,这里不再给出,时间复杂度O(n^2)

 

首先来看看如果可以比较大小:

平均时间复杂度为线性O(n),基于分治法的线性时间求主元素算法。算法思想中位数:数列排序后位于最中间的那个数。如果一个数列有主元素,那么必然是其中位数。求一个数列有没有主元素,只要看中位数是不是主元素。找中位数的方法:选择一个元素作为划分起点,然后用快速排序的方法将小于它的移动到左边,大于它的移动到右边。这样就将元素划分为两个部分。此时,划分元素所在位置为k。如果k>n/2,那么继续用同样的方法在左边部分找;如果k平均时间复杂度为O(n)的时间内找出一个数列的中位数,但最坏时间复杂度O(n^2)。然后再用O(n)的时间检查它是否是主元素。。C语言源码如下:

  1. int partition(int a[],int low,int high){      
  2.     int pivotkey = a[low];      
  3.     while(low
  4.     {          
  5.         if(low=pivotkey)             
  6.             -–high;          
  7.         if(low
  8.             a[low]=a[high];  
  9.             low++;  
  10.         }          
  11.         if(low
  12.             ++low;       
  13.         if(low
  14.             a[high]=a[low];  
  15.             --high;  
  16.         }          
  17.     }         
  18.     a[low]=pivotkey;        
  19.     return low;}  
  20. //快排  
  21. void quick_sort(int a[],int low,int high){     
  22.     if(low
  23.     {         
  24.         int position = partition(a,low,high);          
  25.         if(position>n/2)             
  26.             quick_sort(a,low,position-1);         
  27.         else if(position
  28.             quick_sort(a,position+1,high);         
  29.         else             
  30.             mid=a[position];//找到中位数      
  31.     }  
  32. }  
  33. int main(){      
  34.     int a[100];      
  35.     printf("请输入个数n\n");     
  36.     scanf("%d",&n);      
  37.     for(int i=1;i<=n;i++)     
  38.     {          
  39.         a[i]=0;//初始化     
  40.     }     
  41.     for(int i=1;i<=n;i++)    
  42.     {         
  43.         scanf("%d",&a[i]);     
  44.     }     
  45.     quick_sort(a,1,n);    
  46.     int count=0;      
  47.     for(int i=1;i<=n;i++)//中位数个数     
  48.     {      
  49.         if(a[i] == mid)       
  50.             count++;    
  51.     }  
  52.     if(count > n / 2)        
  53.         printf("有主元素为 %d 出现了 %d 次\n",mid,count);     
  54.     else        
  55.         printf("无主元素\n");     
  56.     system("pause");  
  57. }  


 

下面来看如果不可以比较大小只可以比较是否相等的情况:

下面来看看如果无序,不能比较大小的算法,具体思想就是在一个集合中,删除两个不同的数,则集合的主元素保持不变。根据这个原理,可以很快求出主元素。只有最后剩下的元素才可能是主元素。

  1. #include   
  2. int getMainElement(int a[],int len){  
  3.     int i,mainElement,repeatTimes = 0;  
  4.   
  5.     //每次若不相同则减小这个计数,若相同则增加  
  6.     for(i = 0;i
  7.         if(repeatTimes == 0){  
  8.             mainElement = a[i];  
  9.             repeatTimes = 1;  
  10.         }  
  11.         else{  
  12.             if(mainElement == a[i])  
  13.                 repeatTimes++;  
  14.             else  
  15.                 repeatTimes--;  
  16.         }  
  17.     }  
  18.     return mainElement;  
  19. }  
  20.   
  21. int main(){  
  22.     while(1){  
  23.         int len,i,mainElement,flagCount = 0;  
  24.         scanf("%d",&len);  
  25.         int *a = new int[len];  
  26.         for(i = 0;i
  27.             scanf("%d",&a[i]);  
  28.         }  
  29.   
  30.         mainElement = getMainElement(a,len);  
  31.   
  32.         for(i = 0;i
  33.             if(mainElement == a[i])  
  34.                 flagCount++;  
  35.         }  
  36.   
  37.         if(flagCount>len/2)  
  38.             printf("%d\n",mainElement);  
  39.         else  
  40.             printf("None\n");  
  41.     }  
  42.   
  43.     return 0;  
  44. }  


 


2.有N个人,其中某些人是诚实的,某些人可能会说谎。现在需要进行一项调查,该调查由一系列测试构成。每次测试如下进行:选2个人,然后提问:对方是否诚实?每个人的回答只能是“是”或者“否”。假定在这些人中,所有诚实的人回答都是正确的,而其他人的回答则不能肯定是否正确。如果诚实的人数>n/2,试设计一个调查算法,以最小的测试次数从其中找出一个诚实的人。

 

 

你可能感兴趣的:(分治)