一个计算矩形体的数学编程题记录
题目大概如下:
给定一个给定大小的立方体:
2x3x6;
3x3x3;
3x5x6;
之后计算这个立方体中小矩形的数量,
组成一个最小的其中单位的大小为1,
也就是最小的立方体在原立方体中占
的位置为1x1x1;
但是同样的1x1x2这个矩形也会从2x3x6
中去获取。
那么计算这道题的思路一开始我想到了
排列组合。
继而我想,三维的问题,先通过解决二维
的问题来解决,也就是先通过解决原立方体上
一个面上的问题继而再解决它对应的三维方向
上的其他问题。
(1)如上图1,ogirinalShape是原立方体上一个2x3的横截面,
而构成这个横截面的坐标如果以1x1这个二维最小单位去区分,
会分为如图那样以一些“点”为端点的许多的坐标组出现。
同样在
这个动图中,通过蓝色透明层(也就是countShape,用来统计一个给定大小的平面
上有几个不同的1x1的大小的矩形存在),来统计计算countShape在originalShape中
出现的不同变种,
ok,当countShape随着从1x1开始不断根据originalShape大小,而不断变化,
并且不会有重复占用位置的大小的数据遍历之后,也就是说明了这个二维层面
上的小矩形体可以存在的数量。
计算这个数量我考虑到用到2x3这个大小的(2+1)x(3+1)= 12
个坐标数据(最大外框坐标),并且对应的变化到countShape可以变化到
得到的不同的坐标数据(countShape坐标),去用编程求解。
这是第一步。
(2)如上图2,假设有一辆疾驰而来的列车,列车载着有不同车厢里
有相同的列车识别码的人们,比如1号车厢里的为9901A,同样地,如果
有8节车厢,那么每一节车厢都会有这个9901A,那么相同列车识别码
的人,他们会参加一个列车长组织的抽奖活动,抽奖活动会最后公布一个
列车活动组合码,活动组合码的规则就是说相同列车识别码的人去合并
起来组成一个“列车链”,而最终这个链有多长是随机的,也就是可以是
长度1,即不跟其他车厢的人组合,也可能是8,可能是5.
而最终列车长公布抽奖结果后,这个码就是对应列车识别码组合的组合码。
同样的,列车识别码不会有不同长度的存在。
这样去思考后,我觉得去计算第三维度的小矩形体的数量就可以根据在
列车长度上出现的组合码的组合变化数量来进行计算。
即最简单的1+2+.....+100,车厢号累加的最后数值。
(3)通过第三维度不同大小的伸缩,得到了第三维度的这个z轴上计算的
乘数,那么我预测最终的问题的结果就是一个面上出现的不同矩形的数量,
乘以z轴计算的第二步骤的累加值。
通过组合数学,计算变长为x*y的矩形中有多少个不同形状的矩形
其公式为:
C(x,2) * C(y,2)
当我们题目为2x2的矩形里有几个小矩形,
我们可以看到组合为2x2的矩形一条边上存在3个坐标,
而对应两个方向2,也就是x轴,y轴之后
可以得到公式(也就是说2指明组合中的有哪几个方向,并且每个方向上的长度构成相同,
对应可以尝试在多边形进行测试)
C(3,2) * C(3,2) = (3*2/2)*(3*2/2) = 9
同样对于2, 3边长的矩形来说
C(3,2) * C(4,2) = (3*2/2)*(4*3/2) = 18
countShape的数值现在根据组合数学更好地得出结果,
那么再乘以第三维度的z轴累加值即可得到结果。
最终这个题目的结果公式:
(((x+1)*x)/2 * ((y+1)*y)/2) * ((z/2) * (1+z))
其中(((x+1)x)/2 * ((y+1)y)/2)是第一步获取的组合数量countShape
第二个则是第三维轴上伸缩可能的数字。
而在编程中的格式中,需要用到BigInteger这里也只是对公式进行了转换
import static java.math.BigInteger.valueOf;
import java.math.BigInteger;
class Kata {
public static BigInteger subcuboids(int x, int y, int z) {
//(((x+1)*x)/2 * ((y+1)*y)/2) * ((1+z) * (z/2))
BigInteger xComponents = valueOf(x++).multiply(valueOf(x)).divide(valueOf(2));
BigInteger yComponents = valueOf(y++).multiply(valueOf(y)).divide(valueOf(2));
BigInteger zComponents = valueOf(z++).multiply(valueOf(z)).divide(valueOf(2));
return xComponents.multiply(yComponents).multiply(zComponents);
}
}
同样的,即然公式有了,并且可以看到每个乘积也都是一致的获取方式,
那么怎样去简化呢?
return Stream.of(x,y,z)
.map(dimension->valueOf(dimension++).multiply(valueOf(dimension)).divide(valueOf(2)))
.reduce((l,r)->l.multiply(r))
.get();
虽然看上去不重复了,但是实际上是一个意思,并且也不太可能有那种多余3个维度(可不可能)的题目来让(x,y,z)变得不确定数量,从而利用Stream.of(集合)可以相应去简化。
做这个题目也查了相关的组合数学,但大多数baidu可以查到的都只是比较简单的二维平面
上的不管是数字还是形状组合,而多余二维甚至多余三维(可不可能)的题目少之又少。
相关资料:
排列组合Cn和An公式分别是什么?
百度知道排列组合
知乎排列组合
雨露学习互助-用排列组合解下列有几个矩形
本文来自博客园,作者:ukyo--碳水化合物,转载请注明原文链接:https://www.cnblogs.com/ukzq/p/17069810.html