hdu 1466 计算直线的交点数 递推

题目描述

平面上有n条直线,且无三线共点,问这些直线能有多少种不同交点数。
比如,如果n=2,则可能的交点数量为0(平行)或者1(不平行)。

输入

输入数据包含多个测试实例,每个测试实例占一行,每行包含一个正整数n(n<=20),n表示直线的数量.

输出

每个测试实例对应一行输出,从小到大列出所有相交方案,其中每个数为可能的交点数,每行的整数之间用一个空格隔开。

样例输入
2
3
样例输出
0 1
0 2 3

题解:我们可以从n-1条直线相交的情况推导出n条直线的相交情况,考虑到直线的关系不是相交就是平行,我们可以推倒一下n=4的情况:

  已知n=3时有0,2,3;

  (1):第四条直线与前三条平行,则有0;

  (2):第四条直线与其中两条平行,则有3;

  (3):第四条直线与其中一条平行,则有4,5;

  (4):第四条直线不与任何直线平行,则有3,5,6;

  大致可以知道当有j条边与第n条直线不平行是时候有(n-j)*j加上j条直线的交点,

  得出状态dp[j][j条边的交点]存在,得出状态dp[n][(n-j)*j+j条直线的交点]存在

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
using namespace std;
#define lowbit(x) (x&(-x))
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define MAX 100000000000000000
#define MOD 1000000007
#define pi acos(-1.0)
#define ei exp(1)
#define PI 3.141592653589793238462
#define INF 0x3f3f3f3f3f
#define mem(a) (memset(a,0,sizeof(a)))
typedef long long ll;
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
bool cmp(int x,int y)
{
    return x>y;
}
//const int N=10005;
const int mod=1e9+7;
#define N 200//当n=20的时候交点数目最多为n*(n-1)/2 < 200
int dp[21][N];//dp[直线的总数][交点的个数] = 状态(本状态存在为1,否则为0)
int main ()
{
    int i,n,j,k;
    for (i=0;i<21;i++)
        dp[i][0]=1;//所有的直线都平行
    for (i=2;i<21;i++)//枚举n的值,并且打标
        for (j=1;j<i;j++)//枚举与i相交的边的数目
            for (k=0;k<N;k++)//枚举j条边的交点情况
                if (dp[j][k])//如果存在则推论成功
                    dp[i][(i-j)*j+k] = 1;
    while(cin>>n){
        for(i=0;i<N;i++){
            if(dp[n][i]){
                if (i) cout<<" ";
                cout<<i;
            }
        }
        cout<<endl;
    }
    return 0;
}
posted @ 2017-08-01 14:23  wydxry  阅读(474)  评论(0编辑  收藏  举报
Live2D