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>



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值