题目说明
假设分别将 3 根长度相同的绳子摆成 3 个四边形。
其中 2 根摆成长方形,剩下 1 根摆成正方形。
这时,会出现 2 个长方形的面积之和等于正方形面积的情况
(假设长方形和正方形的各边长都为整数)。例如:
● 绳子长度为20时,可以折出以下这些正方形和长方形。
第 1 根 长 1× 宽 9 的长方形 → 面积= 9
第 2 根 长 2× 宽 8 的长方形 → 面积= 16
第 3 根 长 5× 宽 5 的正方形 → 面积= 25进一步改变绳子长度并摆成长方形和正方形,统计满足条件的长方形和正方形的组合。
这里,将同比整数倍的结果看作同一种解法。例如:绳子长度为40, 60, …时,
可以通过对上例进行等比运算得出以下这些正方形和长方形的组合,
但要将它们看作同一种解法,所以这一类只统计为1种。● 绳子长度= 40
第 1 根 长 2× 宽 18 的长方形 → 面积= 36
第 2 根 长 4× 宽 16 的长方形 → 面积= 64
第 3 根 长 10× 宽 10 的正方形 → 面积= 100
● 绳子长度= 60
第 1 根 长 3× 宽 27 的长方形 → 面积= 81
第 2 根 长 6× 宽 24 的长方形 → 面积= 144
第 3 根 长 15× 宽 15 的正方形 → 面积= 225求绳子长度从 1 增长到 500 时,
共有多少种组合能使摆出的 2 个长方形面积之和等于正方形的面积?
思路
1.因为长宽均为整数,所以长度不能被4整除的绳子直接略过
2.通过绳子的长度可以计算出正方形的边长:len / 4
3.通过绳子的长度可以计算出长方形长宽的所有可能性:宽 < 正方形的边长 < 长
4.双重循环罗列出两个长方形的所有长宽组合,并计算面积之和
5.找出面积之和等于正方形面积的结果
6.对得到的结果进行筛选
1) 长方形自身的长宽互换记为同一个长方形;==> 循环中加入(宽 < 正方形的边长 < 长)条件可以排除这种情况
2) 两个长方形的交换记为同一种组合;==> 使用List<String>记录第一个长方形的所有长宽组合,然后对第二个长方形的长宽组合进行判断是否已经存在
3) 相同比例的组合记为同一种;==> 使用HashMap<Integer,Integer>记录每种正确结果中两个长方形的长宽比(因为List<String>已经规避掉了长方形交换的情况,所以Map中只存一个长方形的长宽比即可)
代码
private static Map<Double,Double> hmap = new HashMap<>(); // 存放两个长方形的宽高比
private static int count = 0; // 统计成功组合的数量
public static void main(String[] args) {
// 绳子长度从4~500
for(int l = 4; l <= 500; l += 4){
print(l);
}
System.out.println("count = " + count);
}
/**
* 打印出指定长度的绳子能得到的所有正确组合
* @param len 绳子长度
*/
public static void print(int len){
if(len < 4 || len % 4 != 0) return ; // 因为要求正方形长方形边长均为整数,所以错误长度直接略过
// 正方形的面积
int square = (len / 4 ) * (len / 4);
// 记录第一个长方形每一种长宽组合。用于判断某一种长宽组合是否已存在
List<String> list = new ArrayList<>();
// a是第一个矩形的宽;b是第一个矩形的长
for(int a = 1,b = len / 2 - a ; a < len / 4; a ++, b--){ // 宽 < 正方形边长 < 长。
list.add(a+","+b); // 记录第一个长方形的每一组长宽
// m是第二个矩形的宽;n是第二个矩形的长
for(int m = 1,n = len / 2 - m ; m < len / 4; m ++, n--){
if(a*b + m*n == square){ // 两个长方形的面积之和等于正方形的面积
if(hmap.containsKey(1.0*b/a)){ // 判断长宽比是否已经存在过
if(Double.compare(hmap.get(1.0*b/a), 1.0*n/m) == 0){ // 已存在
continue; // 相同比例的长宽组合记为一种
}
}
if(list.contains(m+","+n)) continue; // 判断第二个长方形的长宽组合是否是第一个长方形使用过的
hmap.put(1.0*b/a, 1.0*n/m); // 第一个矩形的长宽比;第二个矩形的长宽比
// hmap.put(1.0*n/m, 1.0*b/a); // 如果不使用List,也可以加上这一句来避免两个长方形交换的情况
count ++; // 正确组合+1
System.out.println(a + " * " + b + " + " + m + " * " + n + " = " + (len/4) + " * " + (len/4) + " --> " + square);
}
}
}
}
结果
1 * 9 + 2 * 8 = 5 * 5 --> 25
1 * 25 + 8 * 18 = 13 * 13 --> 169
2 * 32 + 9 * 25 = 17 * 17 --> 289
1 * 49 + 18 * 32 = 25 * 25 --> 625
8 * 50 + 9 * 49 = 29 * 29 --> 841
2 * 72 + 25 * 49 = 37 * 37 --> 1369
1 * 81 + 32 * 50 = 41 * 41 --> 1681
8 * 98 + 25 * 81 = 53 * 53 --> 2809
1 * 121 + 50 * 72 = 61 * 61 --> 3721
2 * 128 + 49 * 81 = 65 * 65 --> 4225
9 * 121 + 32 * 98 = 65 * 65 --> 4225
18 * 128 + 25 * 121 = 73 * 73 --> 5329
1 * 169 + 72 * 98 = 85 * 85 --> 7225
8 * 162 + 49 * 121 = 85 * 85 --> 7225
9 * 169 + 50 * 128 = 89 * 89 --> 7921
25 * 169 + 32 * 162 = 97 * 97 --> 9409
2 * 200 + 81 * 121 = 101 * 101 --> 10201
18 * 200 + 49 * 169 = 109 * 109 --> 11881
1 * 225 + 98 * 128 = 113 * 113 --> 12769
8 * 242 + 81 * 169 = 125 * 125 --> 15625
count = 20
(如果长方形自身的长宽交换算两种,则结果*2)
(如果两个长方形位置交换算两种,则结果*2)