###思路
首先在进行题目之前,我们先想一下,直线之间在一个平面中的状态——无非就是相交或者平行,那么对于2条直线,从其中选一条,最多可以1条直线相交,最大交点数为2,对于3条直线,从其中选一条,最多可以与2条直线相交,另取一条直线可与剩下一条有有交点,以此类推,对于n条无三线共点的直线有n - 1 + n - 2 + ... + 1个交点,即(n - 1)* n / 2
现在以n = 5 为例做分析:
当平行直线条数为5时,交点个数为0 = 5 * (5 - 5)
当平行直线条数为4时,交点个数为4 = 4 * (5 - 4)
当平行直线条数为3时,a.<剩下两条直线平行>交点个数为6 = 3 * (5 - 3)+ 0
b.<剩下两条直线相交>交点个数为7 = 3 *(5 - 3) + 1
当平行直线条数为2时, 交点数为 2 * (5 - 2) + 其他三条直线的交点数
当平行直线条数为1时,即所有直线互不平行,交点数为1 * (5 - 1) + 其他四条直线的交点数
因此可以得出规律:
m条直线的交点数 = x * (m - x) + (m - x)条直线交点个数
其中x为m条直线中平行直线的个数
因此我们可以通过这个递推式,逐项求出从x = n 到 x = 1的交点个数,然后在bool数组中对交点个数进行标记(x一定是大于1的,当x == 0时没有具体含义)
###代码实现
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int a[33333];
bool vis[33333];
int n, ans, max_num = -1;
void sep(int x, int num) //在n条直线中有x条平行直线,此种情况对应的交点个数为num
{
if (x == 0) //此时所有条件枚举完成
{
vis[num] = true; //对该种交点情况进行标记
max_num = max(max_num, num); //对交点个数范围进行确定,减少在主函数中搜索的次数
return;
}
for (int i = x; i >= 1; i--) //对所有情况进行枚举
sep(x - i, i * (x - i) + num);
}
int main()
{
cin >> n;
sep(n, 0);
for (int i = 0; i <= max_num; i++) //对答案进行搜索
if(vis[i])ans++;
cout << ans;
return 0;
}