问题描述
小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;
}