不同直线交点问题

问题描述

小C正在研究平面上的一些直线,他发现如果有n条直线,它们之间的交点数量取决于这些直线的相互位置。小C知道,如果两条直线平行,它们没有交点;如果两条直线不平行,则它们会有一个交点。同时,保证不存在三条或以上直线共点的情况。

现在,小C想知道,给定n条直线的情况下,可能存在多少种不同的交点数。比如,当n=2时,可能的交点数为0(平行)或1(不平行)。


测试样例

样例1:

输入:n = 2
输出:[0, 1]

样例2:

输入:n = 3
输出:[0, 2, 3]

样例3:

输入:n = 4
输出:[0, 3, 4, 5, 6]

题解:

        题目看着不难,从2根线到4根线,如果自己画的话,很容易按照平行线的条数来分,(题目也提到不会有多跟线相交一个点)。比如4根线,就有4线平行,3线平行,2线平行,1线平行的情况,接下来分析每种情况:

        4线平行时,没有交点,即0。

        3线平行时,能看出是3个交点,但是为什么是3根呢,发现1根线时交点有1种情况,0个交点,而一根线与三条平行线必有3个交点,于是就有3x1+0个交点。

        2线平行时,有两条游离的线,而两条线有2种情况,0,1个交点,于是交点情况就是2x2+0和2x2+1种,即4,5。

        1线平行时,得出有1x3+0,1x3+2,1x3+3个,即3,5,6个交点。

        但是发现有重复的情况,使用set即可轻松解决,而且还可以帮你排序。一举两得。

        需要从2开始遍历情况,而且每种情况的交点个数都要记录,使用一个<int,vector<int>>的map即可轻松解决。

        注意set遍历使用迭代器。

代码: 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;

vector<int> solution(int n) {
    map<int,vector<int>> ls;
    vector<int> vt;
    vt.push_back(0);
    ls[1]=vt;
    vt.clear();
    for(int i=2;i<=n;i++){
        set<int> st;
        for(int j=i;j>=1;j--){
            if(j==i){
                st.insert(0);
            }
            else{
                for(int k=0;k<ls[i-j].size();k++){
                    st.insert(j*(i-j)+ls[i-j][k]);
                }
            }
        }
        vector<int> nt;
        set<int>::iterator it;
        for(it=st.begin();it!=st.end();it++){
            nt.push_back(*it);
        }
        ls[i]=nt;
        //cout << nt.size() << "\n";
        st.clear();
        nt.clear();
    }
    return ls[n];
}

int main() {

  if (solution(2) == vector<int>{0, 1}) {
    printf("Test passed for n=2\n");
  }

  if (solution(3) == vector<int>{0, 2, 3}) {
    printf("Test passed for n=3\n");
  }

  if (solution(4) == vector<int>{0, 3, 4, 5, 6}) {
    printf("Test passed for n=4\n");
  }

  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值