b=true; } return b; }
(5)完整程序
现在我们就需要把刚才的程序进行组合,构成我们的完整程序:
public class ch2_6 {
/**
* 判断是否全相等,全相等返回true
*/
public static boolean isSame(int[] a) {
int n=0;
boolean b=false; //是否相等,标志
for(int i=0;i
{
if(a[i]==a[i+1]) //如果相邻两个数相等,计数器加1 {
n++; }
if(n==a.length-1) //全部相等判断 b=true; } return b; }
/**
* 显示数组的值
*/
public static void show(int[] a) {
if (a == null) //判断数组是否为空
System.out.println(\
for (int i = 0; i < a.length; i++) //循环输出数组元素 {
System.out.print(a[i] + \ }
System.out.println(); }
public static void main(String args[]) {
int tang[]={10,2,8,22,16,4,10,6,14,20}; //最初小孩手中的糖果个数 int times=0; boolean b=true;
while(isSame(tang)==false) //判断糖果是否分配好,没有就继续分
{
int m=tang[9]; //防止被覆盖,备份 for(int i=9;i>0;i--) //循环分糖果
{
tang[i]=tang[i]/2+tang[i-1]/2; }
tang[0]=tang[0]/2+m/2; //最后一个小孩分糖果
//记录分糖果次数
times++;
System.out.print(\第\次分之后结果: \ show(tang); //显示结果
//糖果为奇数的向老师要糖果
for(int i=0;i<10;i++)
if(tang[i]%2!=0) //如果为奇数,要一个糖果 tang[i]+=1; }
System.out.println(\分糖果次数:\
System.out.println(\每个人最终的糖果个数:\ } }
2.7 天 平 称 物 1.问题描述
有4个砝码,总重量是40克,砝码的质量是整数,且各不相等。请确定它们的质量,使之能称出1~40克任何整数质量的物体。
2.问题分析
这是问题可以采用穷举的办法来实现。假设4块砝码的重量分别为w1、w2、w3、w4,只要穷举出这样的组合{w1、w2、w3、w4},其中,w1、w2、w3、w4互不相等,w1+w2+w3+w4=40,那么组合{w1、w2、w3、w4}就可能是该问题的解。如果这个组合可以称出1~40克的任意质量,那么这个组合就是问题的答案。 (1)确定程序框架 通过前面的问题分析,主要要分两个步骤:首先如何穷举出所有的组合{w1、w2、w3、w4},其中w1、w2、w3、w4互不相等,w1+w2+w3+w4=40。其次,如何判断组合{w1、w2、w3、w4}是否可以称出1~40克的任意质量。为了看得更加清楚,我们可以把称重的结果打印出来。程序的框架如下:
public static void main(String args[]) {
//穷举列出这种组合
//判断当前组合是否可以称出1~40克的任意质量 //打印出称重结果
}
(2)穷举列出各种组合
可以采用多重嵌套的方式实现穷举,为了减少穷举次数,我们可以让内层循环搜索的范围小于外层循环搜索的范围。这样每次得到的组合方式的4个元素都不会相等,同时也不会出现“相同组合,不同排列”的情况。关键代码如下:
for(weight1=1;weight1<=40;weight1++)
for(weight2=weight1+1;weight2<=40-weight1;weight2++)
//注意:内循环起始值为外循环值加1
for(weight3=weight2+1;weight3<=40-weight1-weight2;weight3++) if((weight4=40-weight1-weight2-weight3)>=weight3) {
//验证当前组合是否可以称出1~40克的任意质量
}
(3)判断当前组合是否可以称出1~40克的任意质量
接下来的问题就是如何判断组合{w1、w2、w3、w4}是否可以称出1~40克的任意质量。如果将其用数学表达式写出,就是要判断方程:
a1w1+a2w2+a3w3+a4w4=W a1,a2,a3,a4∈–1,0,1 在W=1,2,3,?,40时是否都有解。注意,该方程的解a1、a2、a3、a4只能从中{–1,0,1}取值。假设存在这样一组解{a1, a2, a3, a4}={1, –1, 0, 1}使得方程: a1w1+a2w2+a3w3+a4w4=7 有解,则有:
1*w1+(–1)*w2+0*w3+1*w4=7
=>w1+w4=W+w2
这样天平的一边放上砝码w1和w4,另一边放上砝码w2和重为7克的物品,这说明砝码{w1、
w2、w3、w4}可以称出7克的质量。同理,如果方程: a1w1+a2w2+a3w3+a4w4=W a1,a2,a3,a4∈–1,0,1
在W=1,2,3,?,40时都有解,那么就说明砝码{w1、w2、w3、w4}组合可以称出1~40克的任意质量。关键代码如下:
Int flag=0; //flag为1代表组合找到了,为0代表组合没找到
for(flag=1,x=1;x<41&&flag==1;x++)
//重物在天平左面,d的各种状态包括:-1:砝码在天平左面;1:砝码在右面;0:不用该砝码
for(flag=0,d1=1;d1>-2;d1--)
for(d2=1;d2>-2&&flag==0;d2--)
for(d3=1;d3>-2&&flag==0;d3--)
for(d4=1;d4>-2&&flag==0;d4--)
if(x==weight1*d1+weight2*d2+weight3*d3+weight4*d4) flag=1;
(4)打印称重结果
砝码的组合找到之后,下面就通过这个组合把如何称重显示出来,过程分析同第(3)步,关键代码如下:
String left = \//a1a2a3a4
for(int i=1;i<=40;i++) //循环40次,打印出每种情况 for(int a1=-1;a1<=1;a1++) //三种状态都循环一遍
for(int a2=-1;a2<=1;a2++)
for(int a3=-1;a3<=1;a3++)
for(int a4=-1;a4<=1;a4++) {
if(i==a1*w4+a2*w3+a3*w2+a4*w1) //如果相等,打印出结果
{
boolean f=true; //表达式右侧第一项标志 left=i+\
switch (a1) //根据状态,修改表达式 {
case -1: //状态-1:左侧,修改左侧表达式 left=left+\ break;
case //状态1:右侧,修改右侧表达式
1:
if(f) //如果是右侧第一项,数值前不用加“+”
right=right+w4;
Else //如果不是右侧第一项,数值前加“+”
right=right+\
f=false; //右侧出现过数值,修改f标志位
break; }
//根据状态,修改表达式
{
//状态-1:左侧,修改左侧表达式
left=left+\
//状态1:右侧,修改右侧表达式
//如果是右侧第一项,数值前不用加“+”
right=right+w3;
right=right+\
//如果不是右侧第一项,数值前加“+”
//右侧出现过数值,修改f标志位
//根据状态,修改表达式
{
//状态-1:左侧,修改左侧表达式
left=left+\
//状态1:右侧,修改右侧表达式
switch(a2) case case }
switch case case
break; if(f) else f=false; break; break; if(f)
-1: 1: (a3) -1: 1: