P2789 直线交点数

题目传送门

我们将n条直线编号,分别称为直线1、直线2、…、直线n。直线2 与直线1 最多有一个交点,直线3与直线1和直线2最多有2个交点,……,直线n与其它 (n1) 条直线最多 (n1) 个交点。

由此看出,n条无三线共点的直线最多的交点数 max=1+2++(n1)=n(n1)/2

但本题我们要求解的是:这 n 条直线共有多少种不同的交点数? 仍然从举例出发。下面列举了 n=1234 四种情况各自的交点情况:

具体分析一下 n=4 的情况:

已确定的交点数量:sum,待确定的直线条数:p,可能造成的交点数:g(int p,int sum)

分情况讨论(对照上面的图):

  • 4条直线平行,则0个交点。

  • 3条直线平行,则1×3=3个交点。

  • 2条直线平行,则这2条直线与另2条直线的交点数为2×2=4, 而另外2条直线之间可能有0个或1个交点 (见 n=2 的情况),共 4 个交点或 5 个交点。其实这里面的4就是前面的调用者把自己知道的已知交点数量做为小纸条传递给下一个分身,让它继续探索到结束。

  • 4条直线均不平行(可看成 1 条直线平行),这 1 条直线与其它 3 条直线的交点数为 3,而其它 3条直线之间的交点数为,共6个交点。

经过以上分析,我们可以得如下结论:

p条直线的交点方案=r条平行线与pr条直线交叉的交点数+(p-r)条直线本身的交点方案

=r×(pr)+(pr)条直线本身的交点方案 1<=r<=p

#include <bits/stdc++.h>

using namespace std;
//https://www.luogu.com.cn/blog/user34320/solution-p2789
using namespace std;
const int N = 310;
bool visit[N];
/**
 对p条直线分情况讨论平行线的条数,已知在有r条平行线时有(p-r)条线与他们相交于p*(p-r)个交点,
 再加上对于这p-r个交点的相交组合即可!!!
 */
/**
 * 功能:讨论处理n条线的交点数情况有哪些
 * @param p n条线
 * @param sum 已经确定的交点数量
 */
void g(int p, int sum) {
    //标记k个结点数量是存在的
    visit[sum] = true;
    //递归出口,如果0条直线,就返回吧
    if (p == 0) return;
    //n条直线中,存在的平行线条数,需要逐个遍历一遍
    for (int r = p; r >= 1; r--)
        g(p - r, r * (p - r) + sum);
}

int main() {
    //输入
    int n, ans;
    cin >> n;
    //从n条直线,交点数量为0(全部平行)开始讨论
    g(n, 0);
    //统计结果
    for (int i = 0; i < N; i++) ans += visit[i];
    //输出结果
    cout << ans;
    return 0;
}
posted @   糖豆爸爸  阅读(177)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
Live2D
点击右上角即可分享
微信分享提示