一道“正方体六个面上的四个角点整数之和相等”的求解问题

题目:
请将8个给定的正整数(如1,2,3,4,5,6,7,8)分别放在一个正方体的8个角的顶点上,以实现如下要求(如果可能):正方体六个面上的四个角点整数之和相等?输出结果如:A1=1,A2=2...

求解如下


算法思路
根据题境,我们先做如下设定和术语说明,以便于后面的讨论:
1、正整数以1,2,3,4,。。。8表示,以便进行分析;
2、正方体顶点标示如上所示;
3、每一个面的四个顶点数总和,我们称为该面的面积;
4、每一条边的两个顶点数和,我们称为该边的长度;

通过分析,可以得到如下断言为真(采用上面设定及术语):
1、每个面的面积相等,且每个面的面积为36/2,即18;
2、正方体的对边相等;
3、整数1和(2,3)不在同一边,整数7和8不在同一边;

根据所得断言,可以得到如下求导公式和约束:
A1=1;
A4=18-A1-A2-A3=17-A2-A3;
A6=18-A1-A2-A5=17-A2-A5;
A7=18-A1-A3-A5=17-A3-A5;
A8=A1+A2-A7=2*A1+A2+A3+A5-18=A2+A3+A5-16;

A2,A3,A5为可变量,但是A2,A3不等于2,3

程序实现
通过以上算法分析,可用程序实现如下(Java实现):

package qinysong.arithmetic;

public class CubeProblem{

public static void main(String[]args){
System.out.println(
" CubeProblembegin........ " );
searchPeekNumber();
System.out.println(
" CubeProblemend........ " );
}

public static void printPeekNumbers( int []peeks){
System.out.println(
" thepeeknumber:A1= " + peeks[ 0 ] + " ;A2= " + peeks[ 1 ]
+ " ;A3= " + peeks[ 2 ] + " ;A4= " + peeks[ 3 ]
+ " ;A5= " + peeks[ 4 ] + " ;A6= " + peeks[ 5 ]
+ " ;A7= " + peeks[ 6 ] + " ;A8= " + peeks[ 7 ]);
}

// 核心函数,探寻各个顶点的数值
public static void searchPeekNumber(){
int []peeks = new int [ 8 ];
int peekNumber = 0 ;
for ( int i = 4 ;i <= 8 ;i ++ ){
peeks[
0 ] = 1 ;
peeks[
1 ] = i;
for ( int j = 4 ;j <= 8 ;j ++ ){
if (hasUsed( 2 ,j,peeks)) continue ;
peeks[
2 ] = j;
peekNumber
= getPeekNumber( 3 ,peeks);
peeks[
3 ] = peekNumber;
for ( int k = 2 ;k <= 8 ;k ++ ){
if (hasUsed( 4 ,k,peeks)) continue ;
peeks[
4 ] = k;
peekNumber
= getPeekNumber( 5 ,peeks);
if (hasUsed( 5 ,peekNumber,peeks)) continue ;
peeks[
5 ] = peekNumber;
peekNumber
= getPeekNumber( 6 ,peeks);
if (hasUsed( 6 ,peekNumber,peeks)) continue ;
peeks[
6 ] = peekNumber;
peekNumber
= getPeekNumber( 7 ,peeks);
if (hasUsed( 7 ,peekNumber,peeks)) continue ;
peeks[
7 ] = peekNumber;
printPeekNumbers(peeks);
}
}
}
}

/**
*判断获取的顶点值是否在之前的顶点使用过
*
@param indexint将要赋值的顶点索引
*
@param peekNumberint获取的顶点值
*
@return boolean是否在之前的顶点使用过
*/
public static boolean hasUsed( int index, int peekNumber, int []peeks){
if (peekNumber <= 0 ) return true ;
for ( int i = 0 ;i < index;i ++ ){
if (peeks[i] == peekNumber){
return true ;
}
}
return false ;
}

/**
*取得某一顶点的数值
*根据推导公式:
*A4=18-A1-A2-A3;A6=18-A1-A2-A5;A7=18-A1-A3-A5;A8=2*A1+A2+A3+A5-18;
*这里取A1=1
*
@param peekint顶点标号
*
@return int顶点数值
*/
public static int getPeekNumber( int peek, int []peeks){
switch (peek){
case 0 :
return 1 ;
case 3 :
return 17 - peeks[ 1 ] - peeks[ 2 ];
case 5 :
return 17 - peeks[ 1 ] - peeks[ 4 ];
case 6 :
return 17 - peeks[ 2 ] - peeks[ 4 ];
case 7 :
return peeks[ 1 ] + peeks[ 2 ] + peeks[ 4 ] - 16 ;
default :
return 0 ;
}
}

}

执行结果如下

CubeProblembegin........
thepeeknumber:A1=1;A2=4;A3=6;A4=7;A5=8;A6=5;A7=3;A8=2
thepeeknumber:A1=1;A2=4;A3=7;A4=6;A5=8;A6=5;A7=2;A8=3
thepeeknumber:A1=1;A2=4;A3=8;A4=5;A5=6;A6=7;A7=3;A8=2
thepeeknumber:A1=1;A2=4;A3=8;A4=5;A5=7;A6=6;A7=2;A8=3
thepeeknumber:A1=1;A2=6;A3=4;A4=7;A5=8;A6=3;A7=5;A8=2
thepeeknumber:A1=1;A2=6;A3=7;A4=4;A5=8;A6=3;A7=2;A8=5
thepeeknumber:A1=1;A2=6;A3=8;A4=3;A5=4;A6=7;A7=5;A8=2
thepeeknumber:A1=1;A2=6;A3=8;A4=3;A5=7;A6=4;A7=2;A8=5
thepeeknumber:A1=1;A2=7;A3=4;A4=6;A5=8;A6=2;A7=5;A8=3
thepeeknumber:A1=1;A2=7;A3=6;A4=4;A5=8;A6=2;A7=3;A8=5
thepeeknumber:A1=1;A2=7;A3=8;A4=2;A5=4;A6=6;A7=5;A8=3
thepeeknumber:A1=1;A2=7;A3=8;A4=2;A5=6;A6=4;A7=3;A8=5
thepeeknumber:A1=1;A2=8;A3=4;A4=5;A5=6;A6=3;A7=7;A8=2
thepeeknumber:A1=1;A2=8;A3=4;A4=5;A5=7;A6=2;A7=6;A8=3
thepeeknumber:A1=1;A2=8;A3=6;A4=3;A5=4;A6=5;A7=7;A8=2
thepeeknumber:A1=1;A2=8;A3=6;A4=3;A5=7;A6=2;A7=4;A8=5
thepeeknumber:A1=1;A2=8;A3=7;A4=2;A5=4;A6=5;A7=6;A8=3
thepeeknumber:A1=1;A2=8;A3=7;A4=2;A5=6;A6=3;A7=4;A8=5
CubeProblemend........


算法特性
因为该算法是根据分析问题的数学模型,找到推导公式及数值约束,然后直接推导答案,而不是采用通过遍历每一种可能性进行判断,所以效率非常好 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值