十二个小球用天平三次称重找出其中唯一一个质量不同(或轻或重)的小球,用java代码实现。
思路:
将十二个小球分别标记为A,B,C,D,E,F,G,H,I,J,K,L,将它们以四个为一组分为三组也就是:第一组:ABCD;第二组:EFGH;第三组:IJKL。
首先我们考虑将第一组和第二组放置在天平两端进行称重(第一次称重),根据称重的结果可分为两种情况:相等和不等。下面会分别介绍两种情况以及后续判断。
1. 第一组与第二组相等。
这是最简单的情况,可以看出显然第一组的四个小球ABCD和第二组的小球EFGH都是正常小球,而质量不同的小球在第三组IJKL中。那么第一组和第二组的8个小球可以作为标准球来使用。
将第三组的四个小球IJKL分成再次分成两组,两两一组。组1,IJ;组2,KL。从第一组里抽出AB组成组3,作为标准球的对照组。
先用组1和组3称重(第二次称重)。
(1) 组1和组3相等。
则不同的小球在组2——K,L——之中。
之后用K与组3中抽出的A称重(第三次称重)。
如果相等,则不同的小球为L,若不等则不同的小球为K。
(2)组1和组3不等。
则不同的小球在组1——I,J——之中。
之后用I和组3抽出的标准球A称重(第三次称重)。
如果相等,则不同小球为J;若不等则不同小球为I。
2. 第一组和第二组不等。
这个情况要比上面的复杂的多了,因为根据称重结果第三组IJKL没有任何问题,不同的小球在第一组和第二组的八个球之中,那么我们剩余的两次称重必须要处理8个小球。
首先我们继续把ABCDEFGH八个小球分为332三组:组1,ABE;组2,CDF;组3,GH;这样我们能从第二次称重中得到最重要的信息,然后称重组1和组2(第二次称重).
(1)组1和组2相等。
则不同的小球在组3里。
之后从第三组里抽出标准球I和组3的G进行称重(第三次称重)。
如果相等,则不同小球为H,若不等则不同小球为G。
(2)组1和组2不等且倾斜与第一组和第二组称量时相同(即满足第一组>第二组且组1>组2,或第一组<第二组且组1<组2)。
若第二次称重的倾斜状况和第一次相同,说明有问题的小球没有改变位置,则小球E和小球CD是正常小球,质量不同的小球在ABF中间。
之后称重A和B。(第三次称重)
如果AB相等,那么必然是F重量不同。若AB不等,则说明AB质量不同,看此时的倾斜状况是否和第一组一致,那么意味着有问题的小球还是放在和第一次称重同一边,则是A有问题。
(3)组1和组2不等且倾斜与第一组和第二组称量时相反(即满足第一组>第二组且组1<组2,或第一组<第二组且组2>组1)。
若第二次称重和第一次称重倾斜状况不同则表明质量不同的小球换边了,那么小球E和小球CD中有质量不同的小球,ABF是没有问题的。
之后称重CD(第三次称重)。
如果CD相等,那么显然是E重量不同,若是CD不相等,那么对比CD与第一次称重的倾斜方向,若是倾斜方向一致,则说明C有问题,不一致则说明D有问题。
好了,从原理上看,十二小球用天平称三次的解决方案就是以上逻辑。那么接下来看看代码怎么写:
先写小球类
1
/**
2
* 小球类
3
* @author Mqq
4
*
5
*/
6
public class Ball {
7
/* 小球id */
8
private int id;
9
10
11
/* 小球重量 */
12
private double weight;
13
14
/* 初始化 */
15
public Ball(int id, double d) {
16
this.id = id;
17
this.weight = d;
18
}
19
20
21
public int getId() {
22
return id;
23
}
24
25
26
public void setId(Integer id) {
27
this.id = id;
28
}
29
30
31
public double getWeight() {
32
return weight;
33
}
34
35
36
public void setWeight(double weight) {
37
this.weight = weight;
38
}
39
}
40
一个实体类是一个小球,有小球自带的两个属性,编号和重量。
之后我们写一些方法,调用这些方法可以对多个或单个小球进行称重。
1
/**
2
* 0 等于, 1大于,-1小于
3
* @param list1
4
* @param list2
5
* @return
6
*/
7
private static int balence(List<Ball> list1, List<Ball>list2) {
8
9
double weight1 = 0;
10
double weight2 = 0;
11
12
// weight1
13
for(Ball item : list1) {
14
weight1 = weight1+item.getWeight();
15
}
16
17
// weight2
18
for(Ball item : list2) {
19
weight2 = weight2+item.getWeight();
20
}
21
22
return weight1==weight2?0:(weight1>weight2?1:-1);
23
}
24
25
/**
26
* 0 等于, 1大于,-1小于
27
* @param list1
28
* @param list2
29
* @return
30
*/
31
private static int balanceBall(Ball ball1, Ball ball2) {
32
double weight1 = ball1.getWeight();
33
double weight2 = ball2.getWeight();
34
35
return weight1==weight2?0:(weight1>weight2?1:-1);
36
}
接下来按照上面的思路编写算法程序:
1
/**
2
* 查找算法
3
* @param balls
4
* @return
5
*/
6
private static Ball method(List<Ball> balls) {
7
8
if(balls == null || balls.size() < 12) {
9
return null;
10
}
11
12
List<Ball> list1 = new ArrayList<Ball>(balls.subList(0, 4));
13
List<Ball> list2 = new ArrayList<Ball>(balls.subList(4, 8));
14
List<Ball> list3 = new ArrayList<Ball>(balls.subList(8, 12));
15
16
int res = balence(list1, list2);
17
if(res == 0) {
18
/* 如果两个相等那么有问题的是最后一组 */
19
List<Ball> list4 = new ArrayList<Ball>(list3.subList(0, 2));
20
List<Ball> list5 = new ArrayList<Ball>(list3.subList(2, 4));
21
List<Ball> list6 = new ArrayList<Ball>(list2.subList(0, 2));
22
res = balence(list4, list6);
23
if(res == 0) {
24
Ball ball1 = list5.get(0);
25
Ball ball2 = list2.get(0);
26
res = balanceBall(ball1, ball2);
27
if(res == 0) {
28
return list5.get(1);
29
} else {
30
return ball1;
31
}
32
} else {
33
Ball ball1 = list4.get(0);
34
Ball ball2 = list2.get(0);
35
res = balanceBall(ball1, ball2);
36
if(res == 0) {
37
return list4.get(1);
38
} else {
39
return ball1;
40
}
41
}
42
} else {
43
List<Ball> list4 = new ArrayList<Ball>(list1.subList(0, 2));
44
list4.add(list2.get(0));
45
46
List<Ball> list5 = new ArrayList<Ball>(list1.subList(2, 4));
47
list5.add(list2.get(1));
48
49
int res2 = balence(list4, list5);
50
if(res2 == 0) {
51
// 说明这六个都没有问题,有问题的是list2的第三第四个
52
Ball ball1 = list2.get(2);
53
Ball ball2 = list2.get(3);
54
int res3 = balanceBall(ball1, ball2);
55
if(res3 == res) {
56
return ball2;
57
} else {
58
return ball1;
59
}
60
} else if(res2 == res) {
61
// 说明要不list1的01质量有问题,要不, list2的1有问题
62
Ball ball1 = list1.get(0);
63
Ball ball2 = list1.get(1);
64
int res3 = balanceBall(ball1, ball2);
65
if(res3 == 0) {
66
return list2.get(1);
67
} else if(res3 == res) {
68
return ball1;
69
} else {
70
return ball2;
71
}
72
} else {
73
// 说明要不list的23有问题,要不list2的0有问题
74
Ball ball1 = list1.get(2);
75
Ball ball2 = list1.get(3);
76
int res3 = balanceBall(ball1, ball2);
77
if(res3 == 0) {
78
return list2.get(0);
79
} else if(res3 == res) {
80
return ball1;
81
} else {
82
return ball2;
83
}
84
85
}
86
}
87
}
最后main函数这样写:
1
public static void main(String[] arg) {
2
3
/* 创建小球 */
4
int sign = 7;
5
List<Ball> balls = new ArrayList<Ball>();
6
for(int i=1; i<13; i++) {
7
if(i == sign) {
8
Ball ball = new Ball(i, 12.0);
9
balls.add(ball);
10
} else {
11
Ball ball = new Ball(i, 10.0);
12
balls.add(ball);
13
}
14
}
15
16
/* 三次称重,得到结果 */
17
Ball ball = method(balls);
18
if(ball == null) {
19
System.out.println("没找到重量不同的小球");
20
}
21
System.out.println("质量不同的小球号码是:"+ball.getId()+", 质量是"+ball.getWeight()+".");
22
}
这样就简单实现的十二小球三次称重找其中质量不同的一个的问题。