分治法(二)—— 芯片测试

芯片测试

测试方法:将两片芯片(a,b)置于测试台上,互相进行测试,测试报告为“好”或“坏”,只取其一。

假设:好芯片的报告一定是正确的,坏芯片的报告是不确定的(可能会出错)

测试结果分析:

A报告 B报告 结论
B是好的 A是好的 AB都好或AB都坏
B是好的 A是坏的 至少一片是坏的
B是坏的 A是好的 至少一片是坏的
B是坏的 A是坏的 至少一片是坏的

输入:n片芯片,其中好芯片至少比坏芯片多一片

问题:设计一种测试方法,通过测试从n片芯片中挑出一片好芯片。

要求:使用最少的测试次数

结论:至少一半的芯片报“好”,则该芯片为好芯片。

          超过一半芯片报“坏”,则该芯片是坏芯片。

分治法设计思想:

假设n为偶数,将n片芯片凉凉一组做测试淘汰,剩下芯片作为子问题,进入下一轮分组淘汰。

淘汰规则:“好”,“好”  -> 任意留一片,进入下一轮(因为前提是好芯片比坏芯片至少多一片,如果一共有奇数个,根据单个的轮空,其中一定会有两个好的在一组或者轮空的是一个好的,所以这样的规则可以留下一个好的)

                  其他情况-> 全部抛弃(一好一坏或者两个坏的一定会有一个坏的,这样可以淘汰两个坏的或者一好一坏,不会影响剩余留下来的同样是好的比坏的至少多一)

上面说了 当数量为奇数时需要对单个芯片进行轮空操作:处理办法时对该单个轮空芯片进行单独测试,用其余所有芯片对其进行测试,如果至少一般芯片报好,则该芯片为好芯片,直接返回该芯片即可;如果该芯片是坏芯片,则舍弃该芯片,这样对单独的芯片进行处理了以后,就可以进行两两测试了。

为了方便,我使用了结构体存芯片,包括芯片编号和芯片的好坏。(下面代码在我自己的测试中没有出错,但是知道是不是有没有考虑到的地方,如果大家发现有错误,欢迎给我指出错误)

//芯片测试

struct Chip{
	int num;    //芯片编号 
	int state;   //好坏 
};


//两个芯片进行测试,2全好,0全坏,1一好一坏   
int judge(Chip *a,Chip *b){
	int count = 0;
	if(a->state==1){
		count=+b->state;   //如果a是好的,判断b的结果与b一致 
	}else if(a->state==0){
		count +=(rand()%2);   //如果a是坏的,判断b可能好可能坏,随机产生 
	} 
	if(b->state==1){
		count += a->state;
	}else if(b->state==0){
		count +=(rand()%2);
	}
	return count;
}

//如果为奇数个 
vector<Chip*> oddTest(vector<Chip*> a){
	int size = a.size();
	vector<Chip*> result;
	
	int count = 0;    //轮空操作   
	for(int i=1;i<size;i++){
		if(a[i]->state ==1){
			count = count + a[0]->state;
		}else{
			count = count + (rand()%2);
		}
	}
	if(count >= size/2){   //如果轮空的是好的 
		result.push_back(a[0]);   //只返回这个  否则舍弃 
	}else{
		for(int i =1;i<size;i+=2){
			int r = judge(a[i],a[i+1]);
			if(r == 2){
				result.push_back(a[i]);   //判断后面的 
			}	 
		}		
	}
	return result; 
} 
//需测芯片个数为偶数 
vector<Chip*> evenTest(vector<Chip*> a){
	int size = a.size();
	vector<Chip*> result;
	for(int i =0;i<size;i+=2){
		int r = judge(a[i],a[i+1]);
		if(r == 2){
			result.push_back(a[i]);
		} 
	}
	return result;	
}



int  test(vector<Chip*> a){
	int n = a.size();//有几个芯片
	if(n==3){
		int r = judge(a[0],a[1]);   //选前两个进行测试 
		if(r==1){                  //如果一好一坏  取第三个 
			return a[2]->num;    
		}else{                     //其他  任取一片 
			return a[0]->num;
		}
	}
	else if(n==2||n==1){
		return a[0]->num;       //任取一片  取第一片 
	} 
	vector<Chip*> next;
	while(n>3){
		if(n%2==0){
		  	next = evenTest(a);
		}else{
			next = oddTest(a);
		}
		return test(next);
	} 	
} 

测试时直接输入芯片的好坏

int main(){
	
//芯片测试    
	vector<Chip*> chip ;
    for(int i=0;i<10;i++){
    	Chip* a = new Chip();
    	a->num = i;
    	cin>>a->state;
    	chip.push_back(a);
	}

	int t = test(chip);
	cout<<"芯片为:"<<t;
	return 0;
}

时间复杂度分析:

\left\{\begin{matrix} W(n) = W(n/2) + O(n)\\ W(1) = W(2) = 0\\\ W(3) = 1 \end{matrix}\right.\Rightarrow W(n) = O(n)

猜你喜欢

转载自blog.csdn.net/u013340360/article/details/81135429