天平称球问题

飞跃颠峰 2011-08-01 11:29:11
已知n个球中有一个重量跟别的球不一样,但不知道它是轻还是重。

用一架天平最少称多少次能找出这个次品?

输出最少次数及称球方案
...全文
1182 108 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
108 条回复
切换为时间正序
请发表友善的回复…
发表回复
hackersun12345 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 106 楼 alexandertech 的回复:]
算出来的不是正解,复杂度再小也没有意义。
这是算法题,首先要解答正确,即能完成题目的要求,其次才是效率的问题。
[/Quote]
同意
飞跃颠峰 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 105 楼 hackersun12345 的回复:]

引用 104 楼 alexandertech 的回复:
你可以去看看我的博客,采用优化的话,复杂度是O(n^3),解几百个球都没问题

二分法复杂度是O(Log2n),测了下100000个球,约一秒钟出结果,当然用你的方法得出的次数要少
[/Quote]

算出来的不是正解,复杂度再小也没有意义。
这是算法题,首先要解答正确,即能完成题目的要求,其次才是效率的问题。
hackersun12345 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 104 楼 alexandertech 的回复:]
你可以去看看我的博客,采用优化的话,复杂度是O(n^3),解几百个球都没问题
[/Quote]
二分法复杂度是O(Log2n),测了下100000个球,约一秒钟出结果,当然用你的方法得出的次数要少
飞跃颠峰 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 103 楼 hackersun12345 的回复:]

引用 100 楼 alexandertech 的回复:
引用 99 楼 hackersun12345 的回复:

3-4个最多2次,
5-8个最多3次,
……
50个最多不是6次吗?2^6,求正解


不是这样的,最少次数并不是二分法
比如12个只需要3次
你可以看看前面人的回帖

网上百度了下,归纳法解的妙,但这种方法在实际当中我觉得是不可行的,时间复杂度太高,仅仅1……
[/Quote]

你可以去看看我的博客,采用优化的话,复杂度是O(n^3),解几百个球都没问题
hackersun12345 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 100 楼 alexandertech 的回复:]
引用 99 楼 hackersun12345 的回复:

3-4个最多2次,
5-8个最多3次,
……
50个最多不是6次吗?2^6,求正解


不是这样的,最少次数并不是二分法
比如12个只需要3次
你可以看看前面人的回帖
[/Quote]
网上百度了下,归纳法解的妙,但这种方法在实际当中我觉得是不可行的,时间复杂度太高,仅仅14个球时,内存就溢出了,如果换成50个球,并有足够的内存,最坏的情况是我们这辈子也看不到结果了。
看来解这题不但要程序写的好,还得是个数学家。做为开发来说,我觉得二分法是个不错的solution
飞跃颠峰 2011-08-18
  • 打赏
  • 举报
回复
[Quote=引用 99 楼 hackersun12345 的回复:]

3-4个最多2次,
5-8个最多3次,
……
50个最多不是6次吗?2^6,求正解
[/Quote]

不是这样的,最少次数并不是二分法
比如12个只需要3次
你可以看看前面人的回帖
飞跃颠峰 2011-08-18
  • 打赏
  • 举报
回复
[Quote=引用 99 楼 hackersun12345 的回复:]

3-4个最多2次,
5-8个最多3次,
……
50个最多不是6次吗?2^6,求正解
[/Quote]

不是这样的,最少次数并不是二分法
比如12个只需要3次
你可以看看前面人的回帖
飞跃颠峰 2011-08-18
  • 打赏
  • 举报
回复
[Quote=引用 99 楼 hackersun12345 的回复:]

3-4个最多2次,
5-8个最多3次,
……
50个最多不是6次吗?2^6,求正解
[/Quote]

不是这样的,最少次数并不是二分法
比如12个只需要3次
你可以看看前面人的回帖
hackersun12345 2011-08-18
  • 打赏
  • 举报
回复
[Quote=引用 97 楼 alexandertech 的回复:]
引用 96 楼 hackersun12345 的回复:

// 只剩最后一个球则一定是非标准球
if (balls.length == 1) return standardWight;
上面代码应该是:
if (balls.length == 1) return balls[0];

大意了


结果也不对呀 50个球称5次就够了
[/Quote]
3-4个最多2次,
5-8个最多3次,
……
50个最多不是6次吗?2^6,求正解
hackersun12345 2011-08-18
  • 打赏
  • 举报
回复
[Quote=引用 97 楼 alexandertech 的回复:]
引用 96 楼 hackersun12345 的回复:

// 只剩最后一个球则一定是非标准球
if (balls.length == 1) return standardWight;
上面代码应该是:
if (balls.length == 1) return balls[0];

大意了


结果也不对呀 50个球称5次就够了
[/Quote]
3-4个,最多2次
5-8个最多3次
9-16最多4次
50个球最多不是6次吗?2^6,难道我理解有误,求正解
飞跃颠峰 2011-08-17
  • 打赏
  • 举报
回复
[Quote=引用 96 楼 hackersun12345 的回复:]

// 只剩最后一个球则一定是非标准球
if (balls.length == 1) return standardWight;
上面代码应该是:
if (balls.length == 1) return balls[0];

大意了
[/Quote]

结果也不对呀 50个球称5次就够了
hackersun12345 2011-08-17
  • 打赏
  • 举报
回复
// 只剩最后一个球则一定是非标准球
if (balls.length == 1) return standardWight;
上面代码应该是:
if (balls.length == 1) return balls[0];

大意了
飞跃颠峰 2011-08-16
  • 打赏
  • 举报
回复

谢谢分享
这个程序不正确啊,我跑了一下,3个球的情况下经常称出非标准球为100
hackersun12345 2011-08-16
  • 打赏
  • 举报
回复

public class Ball {

public int[] balls;

public Ball(int N) {
balls = new int[N];
for (int i = 0; i < N; i++) {
balls[i] = 100;
}
// 随机生成非标准球
balls[Integer.parseInt(Math.round(N * Math.random() * 10) + "") / 10] = 999;
for (int i = 0; i < N; i++) {
System.out.print(balls[i] + ",");
}
System.out.println();
}
}

public class MainTest {

public static void main(String[] args) {
MainTest test = new MainTest();
Ball ball = new Ball(50);
System.out.println("非标准球:" + test.findBall(ball.balls) + " 次数:" + times);
}

// 记录标准重
private int standardWight = -1;
// 遍历次数,每使用天平一次加1
private static int times = 0;

// 递归查找
private int findBall(int[] balls) {

// 只剩最后一个球则一定是非标准球
if (balls.length == 1) return standardWight;
times++;


// 如果是两个球
if (balls.length == 2) {
if (balls[0] == balls[1]) {
return 0;
}
return standardWight == balls[0] ? balls[1] : balls[0];
}

// 折半找中间轴
int middle = balls.length / 2 + balls.length % 2;
if (middle % 2 == 1) middle += 1;
int endPos = middle / 2;
// 判断左半部分是否有非标准球
if (sumWeight(balls, 0, endPos - 1) == sumWeight(balls, endPos, endPos * 2 - 1)) {
standardWight = balls[0];
// if (middle % 2 == 1) {
// times++;
// if (balls[middle - 1] != balls[0]) return balls[middle - 1];
// }
return findBall(getFocusBall(balls, middle, balls.length));
// 判断是否只有3个球,且有非标准球的情况
} else if (middle == 3) {
times++;
return balls[1] == balls[2] ? balls[0] : balls[1];
} else {
// 判断右半部分是否有非标准球
standardWight = balls[middle];
return findBall(getFocusBall(balls, 0, middle));
}

}

private static int sumWeight(int[] balls, int startPos, int endPos) {
int total = 0;
for (int i = startPos; i <= endPos; i++) {
total += balls[i];
}
return total;
}

/**
* 生成新的目标球
* @param balls
* @param startPos
* @param endPos
* @return
*/
private int[] getFocusBall(int[] balls, int startPos, int endPos) {
int[] focusBall = new int[endPos - startPos];
System.out.println("生成新的目标球 起始下标:" + startPos + " 终止坐标:" + (endPos - 1));
for (int i = 0; i < focusBall.length; i++) {
focusBall[i] = balls[i + startPos];
System.out.print(focusBall[i] + ",");
}
System.out.println();
return focusBall;
}
}
随机输出结果:
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,999,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
生成新的目标球 起始下标:26 终止坐标:49
100,100,999,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
生成新的目标球 起始下标:0 终止坐标:11
100,100,999,100,100,100,100,100,100,100,100,100,
生成新的目标球 起始下标:0 终止坐标:5
100,100,999,100,100,100,
生成新的目标球 起始下标:0 终止坐标:3
100,100,999,100,
生成新的目标球 起始下标:2 终止坐标:3
999,100,
非标准球:999 次数:6
ctwoz 2011-08-10
  • 打赏
  • 举报
回复
学习了…
安卓机器人 2011-08-08
  • 打赏
  • 举报
回复
高人啊,哎!算法一直我的弱项,看来思想是关键,学习了!楼主
豌豆 2011-08-08
  • 打赏
  • 举报
回复
先平均分为两组A,B。在将A,B 平均分成两份A1,A2;B1,B2。将A组的两份球放天平上称量假设不平就说明次品在A组,而B组都是好的,这时将B1拿出分别和A1,A2比较重量,一定是有一个不和B1重量相等,另一个和B1相等(假设A1和B1不等),注意A1和B1的重量以B1为标准判断A1中存在的劣质球是轻的还是重的。判断完后再用二分法来找出A1中的劣质球。
(以上是假设球的总量是四的倍数,并且A1是二的倍数,要是和假设不同则减少或增加球的数量削平或补齐。)
茫茫大海 2011-08-08
  • 打赏
  • 举报
回复
[Quote=引用 82 楼 alexandertech 的回复:]
看来是没人解了,上代码:


Java code


package balance;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class WeightBall {
static int round = 1;
static ……
[/Quote]
楼主终于贴代码了,刚在博客里面看了,想法很好!
flyingZippo 2011-08-08
  • 打赏
  • 举报
回复
楼主神人
flyingZippo 2011-08-08
  • 打赏
  • 举报
回复
一直关注,楼主牛叉
加载更多回复(87)

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧