计算直线的交点数
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 44 Accepted Submission(s) : 21
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Input
输入数据包含多个测试实例,每个测试实例占一行,每行包含一个正整数n(n<=20),n表示直线的数量.
Output
每个测试实例对应一行输出,从小到大列出所有相交方案,其中每个数为可能的交点数,每行的整数之间用一个空格隔开。
Sample Input
2 3
Sample Output
0 1 0 2 3
Author
Source
ACM暑期集训队练习赛(九)
# include<stdio.h>
int main()
{
int i,j,k,m,n;
int a[22][200];
for(i=0; i<190; i++)
a[0][i]=0;
for(i=1; i<=20; i++)
{
a[i][0]=1;
for(j=1; j<=(i-1)*i/2; j++)
a[i][j]=0;
for(j=1; j<i; j++)
{
m=i-j;
for(k=0; k<=m*(m-1)/2; k++)
{
if(a[m][k]==1)
a[i][k+j*m]=1;
}
}
}
while(scanf("%d",&n)!=EOF)
{
printf("0");
for(i=1; i<=n*(n-1)/2; i++)
{
if(a[n][i]==1)
printf(" %d",i);
}
printf("\n");
}
return 0;
}
分析:
将n条直线排成一个序列,两条直线最多只有一个交点,三条直线最多有两个交点,直线n 和其他n-1条直线最多有n-1个交点。
由此得出n条直线互不平行且无三线共点的最多交点数:
Max = 1 +2 +……+(n-1)=n(n-1)/2
但本题不这么简单,
这些直线有多少种不同的交点数?
容易列举出i=1,2,3的情况如右图所示,
来分析n=4的情况:
1. 四条直线全部平行,无交点
2. 其中三条平行,交点数: (n-1)*1+0=3;
3. 其中两条平行,而另外两条直线的交点既可能平行也可能相交,因此交点数据分别为:
(n-2)*2+0=4
(n-2)*2+1=5
4. 四条直线互不平行, 交点数为(n-3)*3+3条直线的相交情况:
(n-3)*3+0=3
(n-3)*3+2=5
(n-3)*3+3=6
即n=4时,有0,3, 4, 5, 6个不同的交点数。
从上述n=4的分析过程中,发现:
m条直线的交点数=(m-r)条平行线与r条直线交叉的交点数+r条直线本身的交点数=
(m-r)*r+r条直线之间的交点数。
#include<stdio.h>
#include<string.h>
const int MAX=200;
int main()
{
int n,i,j,k;
int line[21][MAX];
memset(line[1], 0, sizeof(line[1]));
line[1][0]=1;
for (i=2; i<=20; i++) //计算当直线个数为i时的交点情况
{
memset(line[i], 0, sizeof(line[i]));
line[i][0]=1; //无论有几条直线,都会存在交点个数为0的这种情况
for (j=1; j<i; j++) //对i条直线进行划分
{
for (k=0; k<MAX; k++) //计算该种划分情况下,交点的个数
{
if (line[j][k]==1)
{
line[i] (i-j)*j+k]=1; //line[i] (i-j)*j+k]=1表示存在交点个数为(i-j)*j+k
}
}
}
}
while (scanf("%d", &n)!=EOF)
{
for (i=0; i<MAX; i++)
{
if (i==0) printf("0");
else if(line[n][i]==1) printf(" %d", i);
}
printf("\n");
}
return 0;
}