HDOJ1466

计算直线的交点数

题目不是很难,根据点的产生过程,很容易知道,对于n条直线,其产生的交点数在[0,(n-1)n/2]中。其中,当所有的直线都平行时,交点为0;当所有的直线两两相交时,产生的交点数是(n-1)n/2,很容易证明,假设n条直线的两两相交时产生的交点数为s(n),容易得到递推关系式,s(n)=s(n-1)+n-1,即已知n-1条直线两两相交产生的交点数时,第n条直线会与剩下的n-1条直线产生n-1个交点,而s(1)=0,s(2)=1,所以有s(n)=(n-1)n/2。

而对于中间可能出现的交点数就是平行线的问题,因为题目规定无三点共线。从最初的几个情况开始分析,很容易知道,n=1,2,3时的输出情况,分别如下:

0

0,1

0,2,3

考虑当n=4的情况,可以分以下几种:

当第4条与剩下的3条即n-1条直线全部平行,则无交点;

当第4条与其中的2条即n-2条直线平行,则交点数为(n-1)*1+0=3;

当第4条与其中的1条即n-3条直线平行,则这两条平行直线和另外2条直线的交点数为(n-2)*2=4,而另外2条直线可能产生的交点数目在前面已经分析过了,即n=2时的情况[动态规划的思想],因此该种情况下可能交点数为:(n-2)*2+0=4或者(n-2)*2+1=5;

类似地,当第4条与其中的0条即不与任何一条直线平行,交点数为:(n-3)*3+0=3或者(n-3)*3+2=5或者(n-3)*3+3=6;

综上,n=4时,可能的交点数有0,3,4,5,6。

下面考虑最一般的情况,不难得出,当有n条直线时,

n条直线的交点方案数
= (n-r)条平行线与r条直线交叉的交点数 + r条直线本身的交点方案
= (n-r)*r + r条之间本身的交点方案数

声明一个二维数组,dp[x][y]=1表示x条直线可以产生y个交点,按照上述思路进行模拟,因为n<=20,所以最多有(20-1)20/2=190个交点,所以可以直接把这20种情况全部算出来,给定n,输出对应的结果即可。

<span style="background-color: rgb(204, 204, 204);">#include<iostream>
#include<string.h>
using namespace std;
int main()
{
	int dp[21][191];//dp[x][y]表示x条直线可以产生y个交点
	memset(dp,0,sizeof(dp));
	int i,r,j;
	for(i=0;i<21;i++)
	{
		dp[i][0]=1;//任何一条直线都可以产生0个交点
		for(r=0;r<=i;r++)//r条非相互平行线本身的交点情况
		{
			for(j=0;j<191;j++)
			{
				if(dp[r][j]==1)//r条直线可以产生j个交点
				{
					dp[i][(i-r)*r+j]=1;//规律公式
				}
			}
		}
	}
	int n;
	while(cin>>n)
	{
		int t=(n-1)*n/2;
		for(i=0;i<t;i++)
		{
			if(dp[n][i])
			   cout<<i<<" ";
		}
		cout<<t<<endl;
	} 

	return 0;
}</span>


版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-28 00:50:45

HDOJ1466的相关文章