计算几何小结

本文总结了计算几何领域的多种题型及其解题方法,包括点线相交、方向路径问题、正方形组合、扫描线算法、凸包问题、旋转卡壳、半平面交以及圆的并集等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

计算几何的题目也做了挺多的了,一直没想过写个总结

今天刷题刷累了,就写个总结吧

先给出我的做题过程:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=63632#overview

把这个专题里的题一个个地做完,就差不多了。这个专题需要有一定计算几何基础

先说下计算几何题目的类型大致可以分为下面几类:

点、线的相交,方向、路径问题,正方形、矩形的组合问题,矩形的面积并(扫描线),凸包,旋转卡壳,半平面交,圆的并


点、线的相交、方向、路径:

这都是些基本问题,随便搜一下教程都一大堆了,就不说了


正方形组合:

至于正方形、矩形的组合问题,很关键的一个思想就是点的hash,思想参考这篇博文:http://blog.csdn.net/lyy289065406/article/details/6647405

很不错的博文,解决了一直困扰我很久的问题啊


扫描线:

关于扫描线的问题,有n^3、n^2、nlogn这几种做法

n^3做法,就是根据所有的x、y值,把所有矩形拆成一个个的小矩形,然后分别累加

n^2做法,就是根据所有的x值,把所有矩形拆成一个个竖条的小矩形,然后分别累加

而nlogn做法,则是在n^2的做法上运用了线段树


凸包:

凸包的做法有很,网上通行是就是graham扫描了,大致思路就是找到最下的点,然后根据该点对其他点进行排序,然后沿着逆时针或顺时针方向扫过去,当存在已知点不符合凸包的要求时就回退


旋转卡壳:

先给出一个不错的学习链接:http://blog.csdn.net/hanchengxi/article/details/8639476

这篇博文还是写得很全面的,对思路的学习很有帮助,可惜没有实现代码

旋转卡壳可以用来解决的问题挺多的,包括平面最远点对,两多边形最远点对,两多边形最近点对

对于平面最远点对,基本思路就是先求凸包,找出最远点对分布的可能位置,再在凸包上进行旋转卡壳

而两多边形最远点对、最近点对,则是利用有方向的旋转卡壳进行求解


半平面交:

半平面交解决的问题就是:对一个凹多边形,在其内部求一个区域,使区域的每一个点,都可以连一条直线到多边形边界上任意一点。(其实就是求一些直线相交,围成的面积)

半平面交有两种做法,一种是n^2复杂度的,一种是nlogn的做法

n^2的思路还是比较好理解,用每一条边去切割多边形,每次切割之后再在新的基础上进行切割,所有边都切割一次后,剩下的多边形即为所求

至于nlog的做法网上基本上找不到教程,思路可以参考朱泽园的半平面交的论文,而网上实现的代码都是对朱泽园的思路进行过优化的,具体思路就是先对所有边按极角排序,以保证交出来的点都是有序的,然后按照某一方向求直线相交,若交点不在已围成的面积内则回退,如此继续下去,直到遍历完每一条直线

这里给出一个普通半平面交不错的模板:http://blog.csdn.net/accry/article/details/6070621

这个模板里直线是用一般式表示的,由两点的表示转为一般式的方法为:

a = y.y - x.y;  
b = x.x - y.x;  
c = y.x * x.y - x.x * y.y; 
再推荐一个不错的题:http://poj.org/problem?id=1755

这里把一个解不等式的题目转化为了半平面交,很巧妙


圆的并:

圆的并这道题,上海热身赛的时候碰到过,当时根本听都没听说过,赤裸裸的模板题。

回来之后搜了一下,找到这篇大牛博客:http://hi.baidu.com/aekdycoin/blog/item/c1b28e3711246b3f0b55a95e.html

大致思路就是先对每个圆对其他所有圆求交点,与其他每个圆的两个交点中,一个点标志为入点,一个点为出去,这里运用了扫描线时会用到的思想,再把该圆上的交点按角度排序,可以统计出每段圆弧被覆盖的次数,然后把所有只覆盖一次的点连起来,围成的面积就是覆盖两次及以上的面积,再加上对应的弓形(即只覆盖一次的面积)就可以了。具体做法就是对每段只覆盖一次的圆弧,求出对应弓形面积及对应多边形的一条边的有向面积,累加起来就可以了

上面那篇博客里的实现代码很难看懂,这里给出一个好理解的代码:里面area[i]为覆盖i次及以上的面积,对应圆的并即为area[i]

/*
题目:CIRU2
题目来源:SPOJ 8119  https://www.spoj.pl/problems/CIRUT/
题目难度:中等偏难
题目内容或思路:
    圆的面积并
    题意:给n个圆(最多1000个),分别求出覆盖1层的面积、覆盖2层的面积、
        覆盖3层的面积。。。覆盖n层的面积
    方法见AC大牛blog:
    http://hi.baidu.com/aekdycoin/blog/item/c1b28e3711246b3f0b55a95e.html
做题日期:2011.3.27
*/
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <bitset>
#include <cmath>
#include <set>
#include <utility>
#include <ctime>
#define sqr(x) ((x)*(x))
using namespace std;

const int N = 1010;
const double eps = 1e-8;
const double pi = acos(-1.0);
double area[N];
int n;

int dcmp(double x) {
    if (x < -eps) return -1; else return x > eps;
}

struct cp {
    double x, y, r, angle;
    int d;
    cp(){}
    cp(double xx, double yy, double ang = 0, int t = 0) {
        x = xx;  y = yy;  angle = ang;  d = t;
    }
    void get() {
        scanf("%lf%lf%lf", &x, &y, &r);
        d = 1;
    }
}cir[N], tp[N * 2];

double dis(cp a, cp b) {
    return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}

double cross(cp p0, cp p1, cp p2) {
    return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}

int CirCrossCir(cp p1, double r1, cp p2, double r2, cp &cp1, cp &cp2) {//两圆求交点数 ,并用cp1和cp2存储其交点
    double mx = p2.x - p1.x, sx = p2.x + p1.x, mx2 = mx * mx;
    double my = p2.y - p1.y, sy = p2.y + p1.y, my2 = my * my;
    double sq = mx2 + my2, d = -(sq - sqr(r1 - r2)) * (sq - sqr(r1 + r2));//sq为两圆距离的平方和
    if (d + eps < 0) return 0; if (d < eps) d = 0; else d = sqrt(d);
    double x = mx * ((r1 + r2) * (r1 - r2) + mx * sx) + sx * my2;
    double y = my * ((r1 + r2) * (r1 - r2) + my * sy) + sy * mx2;
    double dx = mx * d, dy = my * d; sq *= 2;
    cp1.x = (x - dy) / sq; cp1.y = (y + dx) / sq;
    cp2.x = (x + dy) / sq; cp2.y = (y - dx) / sq;
    if (d > eps) return 2; else return 1;
}

bool circmp(const cp& u, const cp& v) {
    return dcmp(u.r - v.r) < 0;
}

bool cmp(const cp& u, const cp& v) {
    if (dcmp(u.angle - v.angle)) return u.angle < v.angle;
    return u.d > v.d;
}

double calc(cp cir, cp cp1, cp cp2) {
    double ans = (cp2.angle - cp1.angle) * sqr(cir.r)
        - cross(cir, cp1, cp2) + cross(cp(0, 0), cp1, cp2);
    return ans / 2;
}

void CirUnion(cp cir[], int n) {
    cp cp1, cp2;
    sort(cir, cir + n, circmp);
    for (int i = 0; i < n; ++i)
        for (int j = i + 1; j < n; ++j)
            if (dcmp(dis(cir[i], cir[j]) + cir[i].r - cir[j].r) <= 0)
                cir[i].d++;//某圆被覆盖的次数
    for (int i = 0; i < n; ++i) {
        int tn = 0, cnt = 0;
        for (int j = 0; j < n; ++j) {
            if (i == j) continue;
            if (CirCrossCir(cir[i], cir[i].r, cir[j], cir[j].r,
                cp2, cp1) < 2) continue;
            cp1.angle = atan2(cp1.y - cir[i].y, cp1.x - cir[i].x);//求圆心指向交点的向量的极角,注意这里atan2(y,x)函数要先y后x
            cp2.angle = atan2(cp2.y - cir[i].y, cp2.x - cir[i].x);
            //
            cp1.d = 1;    tp[tn++] = cp1;
            cp2.d = -1;   tp[tn++] = cp2;
            if (dcmp(cp1.angle - cp2.angle) > 0) cnt++;
        }
        tp[tn++] = cp(cir[i].x - cir[i].r, cir[i].y, pi, -cnt);//第i个圆的左端点
        tp[tn++] = cp(cir[i].x - cir[i].r, cir[i].y, -pi, cnt);
        sort(tp, tp + tn, cmp);//把交点按极角排序
        int p, s = cir[i].d + tp[0].d;
        for (int j = 1; j < tn; ++j) {
            p = s;  s += tp[j].d;
            printf("%f %f %f %f\n",tp[j-1].x,tp[j].y,tp[j-1].x,tp[j].y);
            area[p] += calc(cir[i], tp[j - 1], tp[j]);//所有被覆盖了p次的圆弧的弦连起来形成的面积,等于覆盖了p次及p次以上的面积,可画图观察
        }
    }
}

void solve() {
    for (int i = 0; i < n; ++i)
        cir[i].get();
    memset(area, 0, sizeof(area));
    CirUnion(cir, n);
    for (int i = 1; i <= n; ++i) {
        area[i] -= area[i + 1];
        printf("[%d] = %.3lf\n", i, area[i]);
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    while (scanf("%d", &n) != EOF) {
        solve();
    }
    return 0;
}

写完这篇小结才发现自己会的原来这么多了,不容易啊!!!总算是不枉费我寒假天天在刷题!!!

内容概要:本文提出了一种融合多尺度Wavelet模型的跨文化英语交际智能模型系统(FL-DP-Wavelet),旨在通过多模态数据融合、多尺度特征提取与跨文化适应性建模,提升智能系统的文化敏感性和语境理解能力。该模型通过结合小波变换与深度学习优化语言信号的时频特征提取,基于跨文化敏感性发展模型(DMIS)构建文化适应性评估模块,并设计多模态数据融合框架,增强跨文化场景下的语义解析鲁棒性。实验结果显示,系统在跨文化语境下的语义理解准确率提升12.7%,文化适应性评分优于基线模型15.3%。 适合人群:从事跨文化交流、国际商务、外语教育的研究人员和技术开发者,特别是对智能系统在跨文化场景中的应用感兴趣的学者和工程师。 使用场景及目标:①跨文化商务谈判、教育合作和公共外交等场景中,需要提升智能系统的文化敏感性和语境理解能力;②帮助系统实现实时文化适应,减少因文化差异引起的语义误判和非语言行为冲突;③通过多模态数据融合,增强智能系统在复杂跨文化环境中的语义解析能力。 其他说明:该研究不仅提出了新的理论框架和技术路径,还在实际应用中验证了其有效性和优越性。未来将聚焦于小波-Transformer耦合、联邦学习隐私保护和在线学习算法,进一步推动系统向自主文化融合演进。
### 计算机视觉课程结课论文选题方向及主题推荐 计算机视觉作为一门跨学科领域,融合了图像处理、模式识别、机器学习等多种技术手段,其研究内容涵盖了从基础理论到实际应用的广泛范畴。以下是几个适合用于计算机视觉课程结课论文的主题方向及相关具体题目: #### 图像分类与目标识别 此方向旨在训练模型以区分不同种类的对象或场景类别。随着深度卷积神经网络的发展,这一领域的精度已经达到了很高水平。 - 基于迁移学习的小样本图像分类方法研究[^3] - 利用预训练模型改进轻量级移动端物体检测器的设计方案[^4] ```python import tensorflow as tf from tensorflow.keras.applications import MobileNetV2 base_model = MobileNetV2(weights="imagenet", include_top=False) for layer in base_model.layers[:-1]: layer.trainable = False model = tf.keras.Sequential([ base_model, tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(10, activation='softmax')]) model.compile(optimizer=tf.optimizers.Adam(), loss='categorical_crossentropy', metrics=['accuracy']) ``` #### 图像分割与语义解析 该部分专注于将图片划分为具有相似特性的区域,并赋予每一块相应的标签描述其含义。 - 结合注意力机制提升UNet架构在医学影像分割中的表现效果评估 - 多尺度特征聚合策略优化遥感卫星照片地物要素提取流程探究[^4] #### 目标检测与跟踪 这是指定位并持续监测视频流内的移动实体位置变化情况的任务类型。 - YOLO系列算法对比实验及其参数调优实践总结[^2] - 跨摄像头行人重识别关键技术难点剖析及解决方案探讨 #### 三维重建与立体视觉 利用双目或多视角拍摄得到的信息恢复真实世界的空间结构关系。 - 单幅RGB-D传感器数据驱动下的室内环境快速建模技术探析 - SLAM系统中前端几何估计模块效率瓶颈突破路径思考 #### 视频分析与行为理解 通过对连续帧序列执行高层次抽象操作来捕捉其中蕴含的动作规律特性。 - SlowFast时空分离表征学习框架加速版实现细节说明[^2] - 社交媒体短视频流行趋势预测基于大规模用户评论情感挖掘关联性验证
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值