题目不是很难,根据点的产生过程,很容易知道,对于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>
版权声明:本文为博主原创文章,未经博主允许不得转载。