题目链接:点击打开链接
计算直线的交点数
比如,如果n=2,则可能的交点数量为0(平行)或者1(不平行)。
2 3
0 1 0 2 3
分析加入第N条直线的情况(这里以N=4为例):
(分类方法:和第N条直线平行的在a组,其余在b组)
1、 第四条与其余直线全部平行 :
0+4*0+0=0;
2、 第四条与其中两条平行:
交点数为0+(n-1)*1+0=3;
3、 第四条与其中一条平行:
这两条平行直线和另外两点直线的交点数为(n-2)*2=4,
而另外两条直线既可能平行也可能相交,
因此可能交点数为: 0+(n-2)* 2+0=4 或者 0+(n-2)*2+1=5
4、 第四条直线不与任何一条直线平行,交点数为:0+(n-3)*3+0=3 或0+ (n-3)*3+2=5 或0+ (n-3)*3+3=6
即n=4时,有0个,3个,4个,5个,6个不同交点数。
所以从上述n=4的分析过程中,我们发现:
m条直线的交点方案数 =(m - r)条平行线与r条直线交叉的交点数 + r条直线本身的交点方案 = (m - r )* r + r 条之间本身的交点方案数(0 < = r < m )
将 n 条直线排成一个序列,直线 2 和直线 1 最多只有一个交点,直线 3 和直线 1 和直线 2 最多有两个交点......直线n和其他 n - 1 条直线最多有 n - 1 个交点,由此得出 n 条直线互不平行且无三线共点的最多交点数:max = 1 + 2 + . . . + (n - 1) = n * (n - 1) / 2
其中每个自由直线与每个平行直线都有一个交点,j自由直线与i平行直线的交点数为 j * i,所以n条直线的交点数等于自由直线与平行直线的交点加上自由直线内部形成的交点。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
bool dp[22][222]; // dp[i][j] = true 表示 i条直线时有 j个交点为真
void init()
{
memset(dp,false,sizeof(dp));
for(int i=1;i<=20;i++) // i表示直线总数
{
dp[i][0]=true; // 总是存在交点为 0 的
for(int j=1;j<i;j++) // j表示平行直线数
{
int m=i-j; // m表示自由直线数
for(int k=0;k<=m*(m-1)/2;k++) // m条自由直线(自由直线互不平行且无三线共点)最多形成 m*(m-1)/2个点
{
if(dp[m][k])
{
dp[i][m*j+k]=true;
}
}
}
}
}
int main()
{
init();
while(~scanf("%d",&n))
{
printf("0");
for(int i=1;i<=n*(n-1)/2;i++)
{
if(dp[n][i])
printf(" %d",i);
}
puts("");
}
return 0;
}