一、问题描述
二、问题分析
此类具体的题目最常见的做法就是模拟求解,在模拟求解的过程中,需要遍历所有可能的情况,然后需要注意的就是如何计算交叉点,这在本书中有提到,也正如Python代码实现,此处不多介绍。
而另一种方法如C/C++实现将具体的问题进行进一步的抽象和转化,将问题简化为若干根直线具有的最多交点数目,再减去鞋带孔自带的交点就是目标所求(读者可以进行简单地验证)。
三、代码实现
1.C/C++实现
#include <iostream>
#include <vector>
using namespace std;
vector<int> joints;
int get_result(int);
int get_joints(int);
int get_result(int n)
{
// 获取 n 对孔时,中间能有的最大交点数
int lines = 2 * n - 1; // 需要连接的线段数
int fixed = 2 * (n - 1); // 已经自带的交点数 = 孔数 - 2
return get_joints(lines) - fixed;
}
int get_joints(int n)
{
// n 条直线能有的最大交点数目
if (n <= 0)
{
joints.clear();
joints.push_back(0);
return 0;
}
while (joints.size() <= size_t(n))
joints.push_back(get_joints(n - 1) + n - 1);
return joints[n];
}
int main()
{
cout << get_result(6) << endl;
return 0;
}
2.Python实现
# coding=utf-8
from itertools import permutations
def count_joint(path):
joints = 0
_len = len(path)
for i in range(_len):
for j in range(i + 1, _len):
if (path[i][0] - path[j][0]) * (path[i][1] - path[j][1]) < 0:
joints += 1
print(path, joints)
return joints
def get_result(n):
perm = tuple(permutations(range(1, n)))
p_len = len(perm)
result = 0
for i in range(p_len): # 左侧排列
for j in range(p_len): # 右侧排列
path = []
left = 0
right = perm[j][0]
for k in range(n - 1):
path.append((left, right))
left = perm[i][k]
path.append((left, right))
if k < n - 2:
right = perm[j][k + 1]
path.append((left, 0))
result = max(count_joint(path), result)
return result
if __name__ == '__main__':
print(get_result(6))
pass