题目分析
题目难度:普及+/提高
小学二年级知识: n条直线相交(没有三点共线),能够得到的最大交点数目为n(n-1)/2
然后本题要求的是n条直线相交(没有三点共线),能够得到多少种不同交点数目的方案?
手动模拟n=4时的情况, 以有多少条平行线为分类讨论的依据
设平行线的数目为k,则k的范围为[1,4];设交点数目为node
交点数目node=平行线与在外面直线形成的交点数目+外面直线自由排列形成的交点数目(有多种可能)
当k=4时,4条直线平行,没有交点,node=0;
当k=3时,3条直线平行,1条直线在外面,node=1*(4-1)=1*3=3
当k=2时,2条直线平行,2条直线在外面,而在外面的两条直线又有两种情况(这两条直线平行,或者相交),所以
node=2*2+0=4或者2*2+1=5
当k=1时,1条直线平行,3条直线外面,而在外面的三条直线将演变成n=3时的分类讨论情况!
下为n=3时的讨论情况(上述为n=4)
当k=3时,node=0
当k=2时,node=2*(3-2)+0=2
当k=1时,1条直线平行,两条直线在外面,演变成n=2的情况,即node=1*(3-1)+0=2或者node=1*(3-1)+1=3
故当n=3时,node=0,2,3有三种方案
再回到n=4时,
现在k=1,1条直线平行,3条直线在外面,而在外面的三条直线的所有交点数目我们已经求出来了(注意这里不能
直接用n=3时的方案数相加,因为会和前面k的其他情况重合,所以必须计算交点数目)
node=1*3+0或者1*3+2或者1*3+3 =3,5,6
综上所述,n=4时,交点数目可能为0,3,4,5,6 即方案总数为5
很显然,递归的思路就出来了。
然后最后再设定好参数变量,out_line表示在外面的直线数量,初始化为n;sum表示当前形成的交点数目,初始化为0;递归终止条件为out_line=0时,即外面没有直线了!
AC代码
//Author:snnu_lgw
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans;
int num[1000]; //数组记录出现的不同的交点数
// out_line条直线在外时 sum为此时形成的交点数目(已经确定的交点数目,即与平行线形成的交点)
void spss(int out_line,int sum)
{
if(out_line==0)
{ //如果在外面的直线为0,即递归可以结束了 其余的直线都已经处理好了
if(num[sum]==0)
ans++;
num[sum] = 1;
return;
}
for(int i=1;i<=out_line;i++)
{ //i表示把外面的直线拉到平行里去
int surplus = i*(out_line-i);//平行交出来的交点数
int next_out_line = out_line-i; //外面的直线数目要进行更新!
spss(next_out_line,sum+surplus);
}
}
int main()
{
int n;
cin>>n;
spss(n,0);//一开始n条直线在外面,然后有n条直线平行,n-1条,n-2条,……1条平行
cout<<ans;
return 0;
}