import java.util.*;class HelloWorld { private int generate() { int sum = 0; for(int i = 37 ; i > 10 ; i--) { for(int j = i ; j > 0 ; j--) { if(i + j < 39) { for(int m = j ; m > 0 ; m--) { if(i + j + m < 40) { int n = 40 - i - j - m; if((n <= m) && this.check(i,j,m,n)) { sum++; } } } } } } return sum; } private boolean check(int n1, int n2, int n3, int n4) { List list = new ArrayList(); int aa = n1; int bb = n2; int cc = n3; int dd = n4; int a = 0; int b = 0; int c = 0; int d = 0; String as = ""; String bs = ""; String cs = ""; String ds = ""; Integer tem = null; for(int i = 0 ; i < 40 ; i++) { tem = (Integer)(i + 1); list.add(tem); } for(int i = 0 ; i < 3 ; i++) { for(int j = 0 ; j < 3 ; j++) { for(int m = 0 ; m < 3 ; m++) { for(int n = 0 ; n < 3 ; n++) { switch(i) { case 0: { a = 0; as = ""; break; } case 1: { a = -aa; as = " - " + aa; break; } case 2: { a = aa; as = " + " + aa; break; } default: { break; } } switch(j) { case 0: { b = 0; bs = ""; break; } case 1: { b = -bb; bs = " - " + bb; break; } case 2: { b = bb; bs = " + " + bb; break; } default: { break; } } switch(m) { case 0: { c = 0; cs = ""; break; } case 1: { c = -cc; cs = " - " + cc; break; } case 2: { c = cc; cs = " + " + cc; break; } default: { break; } } switch(n) { case 0: { d = 0; ds = ""; break; } case 1: { d = -dd; ds = " - " + dd; break; } case 2: { d = dd; ds = " + " + dd; break; } default: { break; } } if(a + b + c + d > 0) { tem = (Integer)(a + b + c + d); list.remove(tem); if(list.isEmpty()) { System.out.println("a = " + aa + " b = " + bb + " c = " + c + " d = " + d); System.out.println("**************************************************************"); return true; } } } } } } return false; } public static void main(String[] args) { HelloWorld hello = new HelloWorld();
System.out.println("There are " + hello.generate() + " results!"); } }---------- java ---------- a = 27 b = 9 c = 3 d = 1 ************************************************************** There are 1 result! Normal Termination 输出完成(耗费 0 秒)。
假设有序列An= {3^0, 3^1, 3^2,...,3^n},
要证明可以用该序列中的1~n个元素通过加减法组合出Sum(An)中的任意整数。
可以用数学归纳法获得证明。
证明:
当n=1,n=2时,可以用手工方法检验该命题是正确的。假设当n=K时该命题成立,即对Sum(AK)中的任意整数p,都可以找到这样的纯加减算法P(AK),使得P(AK)=p。那么当n=K+1时...
对于Sum(AK)中的任意整数P,我们可以用原先的算法P(AK)生成。
对于对于Sum(AK)~Sum(A[K+1])之间的整数,我们把它分成2段:
第一段:Sum(AK)+1 ,..., 3^(K+1)-1,
第二段: 3^(K+1), 3^(K+1)+1, ..., 3^(K+1)+Sum(AK)。
对于第2段的数字q,可以将它拆分成q=3^(K+1)+p,我们可以用Q(A[K+1])=3^(K+1)+P(AK)这样的方法导出算法,因此也是成立的。
然后对于第1段数据进行分析。
高中的数学知识告诉我们,对于公比为q的等比数列{a,a*q,a*q^2,...,a*q^n},其求和公式为
S= a*(1-q^(n+1))/(1-q)。
在本题中,Sum(AK)+1= (3^(K+1)-1)/2 + 1= (3^(K+1)+1)/2 > (3^(K+1)-1)/2。
所以对第一段中的数字q,可以将它拆分为q=3^(K+1)-p,且0<=p<=Sum(AK)。 我们可以用 Q(A[K+1])=3^(K+1)-P(AK)这样的方法导出算法。
因此当n=K+1的时候该命题也是成立的。另外:对于任意序列AN= {a1,a2,...,aN},如果能利用某种加减算法拼接出1~Sum(AN)中的所有整数,那么考虑到加,减两种可能的算法,如果a[N+1]<=Sum(AN)+1,该命题仍然是成立的。而3恰恰是分界线。
for(int i=0;i<n;i++) m+=Math.pow(3,i);
{
private int generate()
{
int sum = 0; for(int i = 37 ; i > 10 ; i--)
{
for(int j = i ; j > 0 ; j--)
{
if(i + j < 39)
{
for(int m = j ; m > 0 ; m--)
{
if(i + j + m < 40)
{
int n = 40 - i - j - m;
if((n <= m) && this.check(i,j,m,n))
{
sum++;
}
}
}
}
}
}
return sum;
}
private boolean check(int n1, int n2, int n3, int n4)
{
List list = new ArrayList(); int aa = n1;
int bb = n2;
int cc = n3;
int dd = n4; int a = 0;
int b = 0;
int c = 0;
int d = 0; String as = "";
String bs = "";
String cs = "";
String ds = ""; Integer tem = null; for(int i = 0 ; i < 40 ; i++)
{
tem = (Integer)(i + 1);
list.add(tem);
} for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
for(int m = 0 ; m < 3 ; m++)
{
for(int n = 0 ; n < 3 ; n++)
{
switch(i)
{
case 0:
{
a = 0;
as = "";
break;
}
case 1:
{
a = -aa;
as = " - " + aa;
break;
}
case 2:
{
a = aa;
as = " + " + aa;
break;
}
default:
{
break;
} }
switch(j)
{
case 0:
{
b = 0;
bs = "";
break;
}
case 1:
{
b = -bb;
bs = " - " + bb;
break;
}
case 2:
{
b = bb;
bs = " + " + bb;
break;
}
default:
{
break;
} }
switch(m)
{
case 0:
{
c = 0;
cs = "";
break;
}
case 1:
{
c = -cc;
cs = " - " + cc;
break;
}
case 2:
{
c = cc;
cs = " + " + cc;
break;
}
default:
{
break;
} }
switch(n)
{
case 0:
{
d = 0;
ds = "";
break;
}
case 1:
{
d = -dd;
ds = " - " + dd;
break;
}
case 2:
{
d = dd;
ds = " + " + dd;
break;
}
default:
{
break;
} }
if(a + b + c + d > 0)
{
tem = (Integer)(a + b + c + d);
list.remove(tem);
if(list.isEmpty())
{
System.out.println("a = " + aa + " b = " + bb + " c = " + c + " d = " + d);
System.out.println("**************************************************************");
return true;
}
}
}
}
}
}
return false;
}
public static void main(String[] args)
{
HelloWorld hello = new HelloWorld();
System.out.println("There are " + hello.generate() + " results!");
}
}---------- java ----------
a = 27 b = 9 c = 3 d = 1
**************************************************************
There are 1 result!
Normal Termination
输出完成(耗费 0 秒)。
因为在check的时候,4个砝码,肯定会被用到....测试四个砝码的组成是否满足可以组成任意1-40的重量,那么boolean tryit(int a,int sum)
{
return(a==sum);
}boolean tryit(int a,int b,int sum)
{
return( a+b==sum ||
-a+b==sum ||
a-b==sum);
} boolean tryit(int a,int b,int c,int sum)
{
return(a+b+c==sum||
a+b-c==sum||
a-b+c==sum||
a-b-c==sum||
-a+b+c==sum||
-a+b-c==sum||
-a-b+c==sum);
}
boolean tryit(int a,int b,int c,int d,int sum)
{
return(
a+b+c+d==sum||
a+b+c-d==sum||
a+b-c+d==sum||
a+b-c-d==sum||
a-b+c+d==sum||
a-b+c-d==sum||
a-b-c+d==sum||
a-b-c-d==sum||
-a+b+c-d==sum||
-a+b-c+d==sum||
-a+b-c-d==sum||
-a-b+c+d==sum||
-a-b+c-d==sum||
-a-b-c+d==sum||
-a-b-c-d==sum
);
}boolean check(int a,int b,int c,int d)
{
boolean flag1=true;
for(int i=1;i<41&&flag1==true;i++)
{
System.out.println("check:"+i);
flag1=(
tryit(a,i)||
tryit(b,i)||
tryit(c,i)||
tryit(d,i)||
tryit(a,b,i)||
tryit(a,c,i)||
tryit(a,d,i)||
tryit(b,c,i)||
tryit(b,d,i)||
tryit(c,d,i)||
tryit(a,b,c,i)||
tryit(a,b,d,i)||
tryit(a,c,d,i)||
tryit(b,c,d,i)||
tryit(a,b,c,d,i)
);
};
System.out.println("the num can do it: "+flag1);
System.out.println();
return flag1;
}
mathDemo() { n1 = 0;
n2 = 0;
n3 = 0;
n4 = 0;
} boolean tryit(int a,int sum)
{
return(a==sum);
}boolean tryit(int a,int b,int sum)
{
return( a+b==sum ||
-a+b==sum ||
a-b==sum);
} boolean tryit(int a,int b,int c,int sum)
{
return(a+b+c==sum||
a+b-c==sum||
a-b+c==sum||
a-b-c==sum||
-a+b+c==sum||
-a+b-c==sum||
-a-b+c==sum);
}
boolean tryit(int a,int b,int c,int d,int sum)
{
return(
a+b+c+d==sum||
a+b+c-d==sum||
a+b-c+d==sum||
a+b-c-d==sum||
a-b+c+d==sum||
a-b+c-d==sum||
a-b-c+d==sum||
a-b-c-d==sum||
-a+b+c-d==sum||
-a+b-c+d==sum||
-a+b-c-d==sum||
-a-b+c+d==sum||
-a-b+c-d==sum||
-a-b-c+d==sum||
-a-b-c-d==sum
);
}boolean check(int a,int b,int c,int d)
{
boolean flag1=true;
for(int i=1;i<41&&flag1==true;i++)
{
System.out.println("check:"+i);
flag1=(
tryit(a,i)||
tryit(b,i)||
tryit(c,i)||
tryit(d,i)||
tryit(a,b,i)||
tryit(a,c,i)||
tryit(a,d,i)||
tryit(b,c,i)||
tryit(b,d,i)||
tryit(c,d,i)||
tryit(a,b,c,i)||
tryit(a,b,d,i)||
tryit(a,c,d,i)||
tryit(b,c,d,i)||
tryit(a,b,c,d,i)
);
};
System.out.println("the num can do it: "+flag1);
System.out.println();
return flag1;
} void xunhuan() {
while (n1 < 41 & (flag == false)) { n2 = 1;
n1++;
while (n2 < 41 - n1 & (flag == false)) { n3 = 1;
n2++;
while (n3 < 41 - n2 - n1 & (flag == false)) {
n3++;
n4 = 40 - n1 - n2 - n3;
System.out.print("use the numb:" + n1 + " " + n2 + " " + n3
+ " " + n4 + " to check"); flag = check(n1, n2, n3, n4); }
}
}
} public static void main(String[] agr) { mathDemo a = new mathDemo();
a.xunhuan();
if (a.flag == true) {
System.out.println(a.n1);
System.out.println(a.n2);
System.out.println(a.n3);
System.out.println(a.n4);
} else {
System.out.println();
System.out.println(a.flag);
System.out.println("can't find numbs...");
} } int n1, n2, n3, n4; boolean flag = false;
}
那么现在我们回到楼主的这道题目:组成1-n的任意砝码重量(整数),要求所用的钱币张数最少,那么怎么组合?
关键:
--------------------------------
砝码的组合,可以选择性的放在左右两边那么可以是加法,也可以是减法
----------------------------------因为可以用减法
于是我们得到:假设已经实现了1-N个数字
那么下一个要取的数A的左边和右边都可以"实现"N个数字
左边的实现方法也就是用A-已经实现的1-n
右边的实现方法也就是用A+已经实现的1-n可能这样说有点郁闷例如因为肯定需要一个数字
所以必须实现:1因为实现了1,那么下一个要取的数字B的左边可以B-1,右边B+1,那么都可以实现一个数字第二个数的左边挨着1实现一个数字就是:2那么第二个要取的数字就是:3
那么右边实现一个数字也就是:4
这个数字的左右两边的1个数字是因为1已经实现而实现的好,现在我们已经实现了:1.2.3.4 四个数字同理,
第三个要取的数的左边和右边都可以实现4个数字
那么左边接着4,就是5.6.7.8这四个数
不难看出第三个数字是9
9的右边我们还可以实现:10.11.12.13这4个数字好,我们已经实现了1.2.3.4......11.12.13这13个数字
那么第四个数字的左边也可以实现13个数字:14.15.16........25.26第四个数字就是:27
27的右边再用+法又可以实现:28.29.30........38.39.40
好了,观察一下不难发现公式为:(0+1)*2+1=3
(1+3)*2+1=9
(1+3+9)+1=8
(1+3+9+27)*2+1=81大家也许会发现,和楼上的公式差不多,也是前面的总和+1
但是因为可以用-法,所以每个数的范围扩大为2倍
{
if(num==2)
{
return (sum<=4);
}
else{
for(int i=1;i<=sum;i++)
{
if(!fun1((sum-i),(num-1)))
continue;
if((i-(sum-i))>(sum-i+1))
continue;
return true;
}
}
return false;
}这个可以判断一个sum重的砸成num块时是否满足楼主要求
第二个是 1 * 3 = 3
第三个是 3 * 3 = 9
第四个是 9 * 3 = 27
......
第n个是 (n - 1) * 3 = 3n - 3这个算法很简单吧 :)
{
private int generate()
{
int sum = 0;for(int i = 37 ; i > 10 ; i--)
{
for(int j = i ; j > 0 ; j--)
{
if(i + j < 39)
{
for(int m = j ; m > 0 ; m--)
{
if(i + j + m < 40)
{
int n = 40 - i - j - m;
if((n <= m) && this.check(i,j,m,n))
{
sum++;
}
}
}
}
}
}
return sum;
}
private boolean check(int n1, int n2, int n3, int n4)
{
List list = new ArrayList();int aa = n1;
int bb = n2;
int cc = n3;
int dd = n4;int a = 0;
int b = 0;
int c = 0;
int d = 0;String as = "";
String bs = "";
String cs = "";
String ds = "";Integer tem = null;for(int i = 0 ; i < 40 ; i++)
{
tem = (Integer)(i + 1);
list.add(tem);
}for(int i = 0 ; i < 3 ; i++)
{
for(int j = 0 ; j < 3 ; j++)
{
for(int m = 0 ; m < 3 ; m++)
{
for(int n = 0 ; n < 3 ; n++)
{
switch(i)
{
case 0:
{
a = 0;
as = "";
break;
}
case 1:
{
a = -aa;
as = " - " + aa;
break;
}
case 2:
{
a = aa;
as = " + " + aa;
break;
}
default:
{
break;
}}
switch(j)
{
case 0:
{
b = 0;
bs = "";
break;
}
case 1:
{
b = -bb;
bs = " - " + bb;
break;
}
case 2:
{
b = bb;
bs = " + " + bb;
break;
}
default:
{
break;
}}
switch(m)
{
case 0:
{
c = 0;
cs = "";
break;
}
case 1:
{
c = -cc;
cs = " - " + cc;
break;
}
case 2:
{
c = cc;
cs = " + " + cc;
break;
}
default:
{
break;
}}
switch(n)
{
case 0:
{
d = 0;
ds = "";
break;
}
case 1:
{
d = -dd;
ds = " - " + dd;
break;
}
case 2:
{
d = dd;
ds = " + " + dd;
break;
}
default:
{
break;
}}
if(a + b + c + d > 0)
{
tem = (Integer)(a + b + c + d);
list.remove(tem);
if(list.isEmpty())
{
System.out.println("a = " + aa + " b = " + bb + " c = " + c + " d = " + d);
System.out.println("**************************************************************");
return true;
}
}
}
}
}
}
return false;
}
public static void main(String[] args)
{
HelloWorld hello = new HelloWorld();System.out.println("There are " + hello.generate() + " results!");
}
}---------- java ----------
a = 27 b = 9 c = 3 d = 1
**************************************************************
一定有一块是1磅!!!!
a0=1;
ai=Sum(a0+...+a[i-1])*2+1,
记得好像是可以用差分方程解出来的,可惜不记得怎么做的了:(
?
1,3,9,27
肯定是错的2就拼不出来了
原因在于:
两个重量不同的砝码可以放在天平的两边产生一个重量为(大砝码-小砝码)重量的砝码
所以可以用-法可是钱的组合,你不可能把一个10块钱和一个3块钱一起给人家,然后告诉人家这是7块钱吧....所以,钱只能用+法....
{
private int generate()
{
int sum = 0;for(int i = 37 ; i > 10 ; i--)
{
for(int j = i ; j > 0 ; j--)
{
if(i + j < 39)
{
for(int m = j ; m > 0 ; m--)
{
if(i + j + m < 40)
{
int n = 40 - i - j - m;
if((n <= m) && this.check(i,j,m,n))
{
sum++;
}
}
}
}
}
}
return sum;
}
private boolean check(int n1, int n2, int n3, int n4)
{
boolean[] check = new boolean[40];
for(int i=0;i<40;i++)
check[i]=false;
for(int i1=-1;i1<=1;i1++)
{
for(int i2=-1;i2<=1;i2++)
{
for(int i3=-1;i3<=1;i3++)
{
for(int i4=-1;i4<=1;i4++)
{
int sum=i1*n1+i2*n2+i3*n3+i4*n4;
if(sum>=1)
check[sum-1]=true;
}
}
}
}
for(int i=0;i<40;i++)
if(check[i]==false)
return false;
System.out.println("a="+n1+" b="+n2+" c="+n3+" d="+n4);
return true;
}
public static void main(String args[])
{
Test newTest= new Test();
System.out.println("There is/are "+newTest.generate()+" result(s).");
}
}答案:a=27 b=9 c=3 d=1
互相学习 互相提高
互相学习 共同提高
问题扩展为称重1-n任意整数磅的物体
首先可以知道一定有1磅的砝码
假设已经找到k个砝码(用a(i)表示,其中i=1...k;a(i)从小到大排列)能够称重1-N磅的任意整数磅的物体
现在考虑增加一个砝码a(k+1)使得k+1个砝码能够称重更多任意整数磅的物体
那么增加的砝码a(k+1)的重量的最大值为2N+1(大家思考一下)
这里有等式
a(1)+a(2)+...+a(i)+...+a(k)=N
a(k+1)=2N+1方便起见记S(k)=a(1)+a(2)+...+a(i)+...+a(k)则a(k+1)=2S(k)+1
(1)当k=1时a(2)=2*a(1)+1=3(2)当k>=2时a(k+1)-a(k)=2S(k)+1-(2S(k-1)+1)=2*a(k)
即 a(k+1)=3*a(k)
为等比数列
a(k)=3^(k-2)*a(2)=3^(k-1) (*)
(*)式也满足a(1)=1的情况
综上有
当k个砝码的重量为a(i)=3^(k-1) 其中i=1....k能够称重1-N任意重量的物体
其中N=S(k)=(3^k - 1)/2
?
1,3,9,27
肯定是错的2就拼不出来了
// 怎么拼不出来天平的左边放 天平的右边
物体+1 3如果平衡 物体=2天平的左边放 天平的右边
物体 1+3如果平衡 物体重=4
依次类推。。
看来写JAVA 要学号数学啊!!!
现在意识到了 !!!!!!!!!!
4个里面取2个有12种方法
4个里面取3个有4种方法
4个里面有取个有1种方法
中共只有21种组成方法 请问 1-40 40种组成方法能成立吗?无解...........................想法很有创意,但是取3个和取4个时并不是一种取法只能表示一种整数质量
比如1,3,9,可以表示13,可以表示5,11,这个题目是可以相减的。另外我觉得这道题的算法毕竟只适用这一类型题,如果求所有解,自然是要有些复杂的算法,
如果只求一个解,3的n次幂就可以了