HDU ACM:1446 計算直線的交點數

Problem Description
平面上有n條直線,且無三線共點,問這些直線能有多少種不同交點數。
比如,如果n=2,則可能的交點數量爲0(平行)或者1(不平行)。
 

Input
輸入數據包含多個測試實例,每個測試實例佔一行,每行包含一個正整數n(n<=20),n表示直線的數量.
 

Output
每個測試實例對應一行輸出,從小到大列出所有相交方案,其中每個數爲可能的交點數,每行的整數之間用一個空格隔開。
 

Sample Input
2 3
 

Sample Output
0 1 0 2 3
 

Author
lcy


問題分析:

1條線:0
2條線:0 1
3條線:0 2 3
4條線:0 3 4 5 6 
……

可以把直線分成兩組,第一組是相互平行的直線,第二組是自由直線,在本組中可以相互平行、相交,但是不能與第一組相平行,否則分組就沒有意義了。

設直線總是爲N,設第一組有i條直線,則第二組N-i有條直線。
以4條線來分析:
1、當i=4,N-i=0時,交點數:0
2、當i=3,N-i=1時,交點數:3條平行線與1條自由線的交點個數+1條自由線能形成的交點個數,即3+0=3
3、當i=2,N-i=2時,交點數:2*2+{0,1}={4,5}
4、當i=1,N-i=3時,交點數:1*3+{0,2,3}={3,5,6}

由此分析:交點數=i*(N-i)+j條自由直線的交點數

實現:

起初想用直接一點的辦法,用二維數組存儲每種N下,可能的交點數。這方法有很多問題,一是會計算出很多重複的可能交點數,二是這些重複的情況會再次出現在後面的調用中,導致可能性非常大,數組難以存儲。

後來的辦法:n條直線的最多可能交點數爲n*(n-1)/2,即前n個自然數的和。20條直線最多有190個交點。用一個二維數組DP[21][200],數組中只保存0、1,用來表示該下標對應的可能交點數是否有效。

例如:DP[3][2]=1,表示總數N爲3條直線的情況下,2個交點的情況有效。

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int DP[21][200];
	int N,n,free,j;
	memset(DP,0,sizeof(DP));
	for(n=1;n<21;n++)
	{
		DP[n][0]=1;
	}
	for(n=1;n<21;n++)             			  	//直線總數
	{
		for(free=0;free<n;free++)  	 			//自由直線總數
		{
			for(j=0;j<n*(n-1)/2;j++)            //可能的交點數
			{
                if(DP[free][j]==1)              //若free條自由直線有j個交點的可能性爲真
				{
					DP[n][free*(n-free)+j]=1;   //那麼n條直線在free條自由直線,n-free條平行直線的情況下
												//的free*(n-free)+j個交點的可能性爲真
				}
			}

		}
	}
	while(scanf("%d",&N)==1)
	{
		int i,top=N*(N-1)/2;
		for(i=0;i<=top;i++)
		{
			if(i==0)//爲HDU ACM格式化輸出
			{
				printf("0");
				continue;
			}
            if(DP[N][i]==1)
			{
				printf(" %d",i);
			}
		}
  		printf("\n");
	}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章