题目
假设平面上有N条直线,且无三线共点,那么这些直线一共能有多少不同的交点数?
输入输出格式
输入格式
一行,一个整数N,代表有N条直线。
输出格式
一行,一个整数,表示方案总数。
输入输出样例
输入样例
4
输出样例
5
解析
我们将n条直线编号,分别称为直线1、直线2、…、直线n。直线2与直线1最多有一个交点,直线3与直线1和直线2最多有2个交点,……,直线n与其它 (n-1) 条直线最多 (n-1) 个交点。
由此看出,n条无三线共点的直线最多的交点数max=1+2+…+(n-1)=n(n-1)/2。
但本题我们要求解的是:这 n 条直线共有多少种不同的交点数?
仍然从举例出发。下面列举了 n=1、2、3、4 四种情况各自的交点情况:
具体分析一下n=4的情况:
(1)4 条直线全部平行,则0交点 {4*(4-4)}。
(2)其中 3 条直线平行,则3交点 {3*(4-3)}。
(3)其中 2 条直线平行,则这2条直线与另2条直线的交点数为4,而另2条直线之间可能有0个或1个交点(见n=2的情况,共4个交点或5个交点。{2*(4-2)+0或1}
(4)4 条直线均不平行(可看成1条直线平行),这1条直线与其它3条直线的交点数为3,而其它3条直线之间的交点数为3,共6个交点。{1*(4-1)+3}
经过以上分析,我们可以得如下结论:
m条直线的交点方案=r条平行线与(m-r)条直线交叉的交点数+(m-r)条直线本身的交点方案
=r*(m-r)+(m-r)条直线本身的交点方案 (1<=r<=m)
在具体编程时,我们设置一个标志数组 f[0..max],在使用上述结论递归求解的过程中,每得到一种交点数k,则置f[k]为true(初始f[0]~f[max]均为false)。
#include<iostream>
#include<memory.h>
#include<algorithm>
using namespace std;
int n,maxn=-1,ans=0;
bool f[11000];
void g(int n,int k){
if(n==0){
f[k]=true;
maxn=max(k,maxn);
}
else{
for(int r=n;r>=1;r--){
g(n-r,r*(n-r)+k);
}
}
}
int main(){
cin>>n;
memset(f,false,sizeof(f));
g(n,0);
for(int i=0;i<=maxn;i++){
if(f[i]){
ans++;
}
}
cout<<ans;
return 0;
}