zoukankan      html  css  js  c++  java
  • 【题解】直线交点数

    题目信息

    题目来源:未知;

    在线评测地址:Luogu#2789

    运行限制:时间 (1.00 extrm{s}),空间 (256 extrm{MiB})

    题目描述

    平面上有 (N) 条直线,且无三线共点,那么这些直线能有多少不同的交点数?

    输入格式

    一个正整数 (N)

    输出格式

    一个整数表示方案总数。

    数据规模及约定

    (Nle 25)

    分析

    题意很清晰,但是要想到正解是比较难的。

    不考虑重合,平面上的两条直线只有平行和相交两种情况。每一组直线相交就会多一个交点。

    同时,平行具有传递性,也就是说对于一组平行的直线,之间没有任何交点。我们定义一组((k) 个)平行线为一个大小为 (k) 的线簇。

    如果现在有两个大小分别为 (a)(b) 的线簇相交,那么就会产生 (ab) 个交点。如果我们统计交点时以线簇为单位统计,就可以达到比较优秀的复杂度。

    考虑 DP,令 (f_{i,j})(i) 条直线时能否产生 (j) 个节点。转移时,枚举大小在 (1)(i) 的线簇,(f_{i,j}=f_{i-1,j-(i-1)}lor f_{i-2,j-2(i-2)}lorcdotslor f_{i-k,j-k(i-k)}lorcdotslor f_{0,j})。特别地,(f_{0,0}=color{lime}{ extrm{True}})

    最后,统计一下 (sum[f_{n,k}=color{lime}{ extrm{True}}]) 即可。

    当然,这道题也可以搜索解答。

    Code

    这道题代码需要注意一下循环的边界。

    #include <cstdio>
    using namespace std;
    
    const int max_n = 25;
    bool dp[max_n+1][max_n*max_n] = {}; // dp[0..n][0..n^2-1]
    
    int main()
    {
    	int n, ans = 0;
    
    	scanf("%d", &n); // 输入
    
    	dp[0][0] = 1;
    	for (int i = 1; i <= n; i++) // 直线的数量
    		for (int j = 0; j < n * n; j++) // 节点的数量
    			for (int k = 1; k <= i; k++) // 线簇的大小
    				dp[i][j] |= dp[i-k][j-(i-k)*k]; // 转移
    	
    	for (int i = 0; i < n * n; i++) // 统计答案
    		ans += dp[n][i];
    
    	printf("%d
    ", ans); // 输出
    	
    	return 0; // 然后就 AC 了、
    }
    
  • 相关阅读:
    mac下crontab定时任务使用
    javascript入门之算术乘法表
    原型模型
    Servlet开发
    工厂模式
    简单工厂模式
    Java设计模式之瞎BB的官话
    JavaBean技术
    软件设计模式之单例模式
    JSP页面请求与响应以及保存页面状态
  • 原文地址:https://www.cnblogs.com/5ab-juruo/p/solution-lg2789.html
Copyright © 2011-2022 走看看