问题描述
有n(2≤n≤20)块芯片,有好有坏,已知好芯片比坏芯片多。
每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏。而用坏芯片测试其他芯片时,会随机给出好或是坏的测试结果(即此结果与被测试芯片实际的好坏无关)。
给出所有芯片的测试结果,问哪些芯片是好芯片。
每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏。而用坏芯片测试其他芯片时,会随机给出好或是坏的测试结果(即此结果与被测试芯片实际的好坏无关)。
给出所有芯片的测试结果,问哪些芯片是好芯片。
输入格式
输入数据第一行为一个整数n,表示芯片个数。
第二行到第n+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本 身进行测试)。
第二行到第n+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本 身进行测试)。
输出格式
按从小到大的顺序输出所有好芯片的编号
样例输入
3
1 0 1
0 1 0
1 0 1
1 0 1
0 1 0
1 0 1
样例输出
1 3
c语言参考答案:
#include
#define MAXS 20
int main()
{
int n, text[20][20], i, j, s;//s为坏芯片数量
scanf("%d", &n);
if (n >= 2 && n <= 20)
{
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", &text[i][j]);
}
}
//剔除坏芯片,留下好芯片
for (j = 0; j < n; j++)
{
s = 0;
for (i = 0; i < n; i++)
{
s += text[i][j];
}
if (s > n/2)
printf("%d ", j+1);
}
}
return 0;
}
c语言参考答案:
#include
#define MAXS 20
int main()
{
}
摘抄:
下面两个结论比较有用,先列出来。
任意拿两片芯片互相测试,则有
1)结果都为真,则说明两片都为真,或者都为假。
2)其他结果,则最少有一为假。
在任意偶数多的芯片里,如果好芯片多于坏芯片,将所有芯片两两分组,根据抽屉原理,则有
1)必有两个好芯片分在一组。
2)同为好芯片的组数一定多于同为坏芯片的组数。
测试流程
1)将芯片两两分组,比如1和2,3和4。。。。2k-1和2k。互相测试,则必有结果同为真的组。
2)保留结果同为真的组,丢弃其他组。必有好芯片组多于坏芯片组。(所以当只有两组或者一组同为真时,则必为真,测试结束)
3)结果同为真的组芯片必定同好或者同坏,所以可以丢弃一半。从所有同真组中任意取出一个丢弃另一个,组成新的测试组,继续两两分组,直到同真组只有2个或者1个测试结束,坚持到最后的就是好芯片。
说 明:同真组可能会变成奇数个,当为奇数组时,任意选一组取其中一个(假设为A),在剩余组中各取一个来测试A,如果测试结果A为好芯片过半或者等于一半, 则A为好芯片,测试结束。否则A为坏芯片,判定A为好芯片的必为坏芯片,剔除后剩余部分形成新的测试组,继续两两分组。。。
总的原理和 淘 金差不多,刚开始好的芯片多,在每次剔除芯片时一定要保证剔除的坏芯片数量一定要多于或者等于好芯片的数量,这样就能保证在剩余的芯片中好的一定多于坏 的。当组数为奇数时采用投票制,多于半数的投票有效(等于也有效,因为好的多于坏的,相等则被测试的一定为好的)。
因为每次最少剔除一半的芯片,所以最坏情况出现在每次只能剔除一半芯片的时候,按等比数列递减。当有N个芯片时,测试次数为n+(n/2)+(n/4)...=2n(实际上当为奇数组时,次数会更多,不过算不过来了,省略)