[CEOI2012]Printed Circuit Board

本文介绍了一种计算从原点可见点数量的算法。通过使用顺时针排序的多边形顶点,利用set数据结构来跟踪可能可见的点,并进行有效判断。文章详细解释了算法原理,并附带完整代码。

题意:给出一个简单多边形,问有多少个点能在原点被看见。
题解:set
先定义next(x)为x的下一个点,prev(x)为x的上一个点,multi(p0,p1,p2)为叉积。假设点的顺序是顺时针,如图所示。

很明显,只需要从右往左的边,也就是multi(O,x,next(x))>0的边,就可以挡住所有的点;换言之,只有这些边上的点有可能被看见。还是简单证明一下吧:对于上面的边(细边)它们已经被下面的边完全挡住了,不用考虑;对于一条在下面的从左往右的边,要从first走到它的起点——也就是左边的点,一定会先越过它;而从它的终点——也就是右边的点,要走到last,也一定会越过它。这两部分一个从这条边上面越过,另一部分从下面越过,一定可以覆盖这条边。
所以我们只需要把所有点按极角排序,从first逆时针扫到last,每个点作为以这个点为起点的边(一定是从右往左的边)插入一个可以插入元素、维护最小值、删除元素的数据结构中(线段树、堆、平衡树都可以实现。我用了set),删除以这个点为终点的边(假如在这个数据结构里的话),每次看看当前点是不是最靠下的(没有被挡住的)。
注意点也是可以挡住视线的,所以最后要处理一下极角相同,也就是与原点在同一条直线上的点,除了最近的,把剩下的都标为看不见就好了。
代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;

long long n,a[200010];
struct pnt
{
    long long x,y;
}p[200010],o;
bool ans[200010],rev=0;

long long next(long long x)
{
    return x==n?1:x+1;
}
long long prev(long long x)
{
    return x==1?n:x-1;
}
long long multi(pnt p0,pnt p1,pnt p2)
{
    long long x1=p1.x-p0.x,y1=p1.y-p0.y,x2=p2.x-p0.x,y2=p2.y-p0.y;
    return x1*y2-x2*y1;
}
long long cmp(long long x,long long y)
{
    return multi(o,p[x],p[y])==0?p[x].x<p[y].x:multi(o,p[x],p[y])>0;
}
void pre()
{
    p[0]=p[n];
    p[n+1]=p[1];
    long long st=1;
    for(long long i=2;i<=n;i++)
    {
        if(multi(o,p[st],p[i])<0||multi(o,p[st],p[i])==0&&p[i].x<p[st].x)
        st=i;
    }
    if(multi(p[st],p[next(st)],p[prev(st)])>0)
    reverse(p,p+2+n),rev=1,st=n-st+1;
    for(long long i=1;i<=n;i++)
    {
        a[i]=i;
    }
    sort(a+1,a+n+1,cmp);
}
struct hhh
{
    long long x;
    hhh(long long _x)
    {
        x=_x;
    }
    bool operator<(hhh y)const
    {
        if(x==y.x)
        return 0;
        return multi(o,p[x],p[y.x])>=0&&multi(p[x],p[next(x)],p[y.x])<=0||multi(o,p[x],p[y.x])<0&&multi(p[y.x],p[next(y.x)],p[x])>0;
    }
};
void out()
{
    if(rev)
    reverse(ans+1,ans+1+n);
    vector<int>hh;
    for(long long i=1;i<=n;i++)
    if(ans[i])
    hh.push_back(i);
    printf("%lld\n",hh.size());
    for(vector<int>::iterator it=hh.begin();it!=hh.end();it++)
    printf("%lld ",*it);
}
set<hhh>s;
bool in[200010];
int main()
{
    o={0,0};
    scanf("%lld",&n);
    for(long long i=1;i<=n;i++)
    scanf("%lld%lld",&p[i].x,&p[i].y);
    pre();
    for(long long i=1;i<=n;i++)
    {
        if(in[prev(a[i])])
        {
            if(s.begin()->x==prev(a[i]))
            ans[a[i]]=1;
            in[prev(a[i])]=0;
            set<hhh>::iterator it=s.lower_bound(hhh(prev(a[i])));
//          it--;
//          printf("%lld %lld\n",it->x,prev(a[i]));
            s.erase(it);
        }
        if(multi(o,p[a[i]],p[next(a[i])])>0)//只有这些边是有用的 
        {
            s.insert(hhh(a[i]));
            in[a[i]]=1;
            long long uu=s.begin()->x;
            if(multi(p[uu],p[next(uu)],p[a[i]])==0)
            ans[a[i]]=1;
        }
        else if(multi(p[s.begin()->x],p[next(s.begin()->x)],p[a[i]])==0)
        ans[a[i]]=1;/*
        printf("%lld\n",a[i]);
        for(long long i=1;i<=n;i++)
        printf("%lld ",in[i]);
        puts("");
        print();*/
    }
    ans[a[n]]=1;
    for(long long i=1,j=1;i<=n;i=j)
    {
        j++;
        while(j<=n&&multi(o,p[a[i]],p[a[j]])==0)
        ans[a[j++]]=0;
    }
    out();
}
内容概要:文章以“智能网页数据标注工具”为例,深入探讨了谷歌浏览器扩展在毕业设计中的实战应用。通过开发具备实体识别、情感分类等功能的浏览器扩展,学生能够融合前端开发、自然语言处理(NLP)、本地存储与模型推理等技术,实现高效的网页数据标注系统。文中详细解析了扩展的技术架构,涵盖Manifest V3配置、内容脚本与Service Worker协作、TensorFlow.js模型在浏览器端的轻量化部署与推理流程,并提供了核心代码实现,包括文本选择、标注工具栏动态生成、高亮显示及模型预测功能。同时展望了多模态标注、主动学习与边缘计算协同等未来发展方向。; 适合人群:具备前端开发基础、熟悉JavaScript和浏览器机制,有一定AI模型应用经验的计算机相关专业本科生或研究生,尤其适合将浏览器扩展与人工智能结合进行毕业设计的学生。; 使用场景及目标:①掌握浏览器扩展开发全流程,理解内容脚本、Service Worker与弹出页的通信机制;②实现在浏览器端运行轻量级AI模型(如NER、情感分析)的技术方案;③构建可用于真实场景的数据标注工具,提升标注效率并探索主动学习、协同标注等智能化功能。; 阅读建议:建议结合代码实例搭建开发环境,逐步实现标注功能并集成本地模型推理。重点关注模型轻量化、内存管理与DOM操作的稳定性,在实践中理解浏览器扩展的安全机制与性能优化策略。
基于Gin+GORM+Casbin+Vue.js的权限管理系统是一个采用前后端分离架构的企业级权限管理解决方案,专为软件工程和计算机科学专业的毕业设计项目开发。该系统基于Go语言构建后端服务,结合Vue.js前端框架,实现了完整的权限控制和管理功能,适用于各类需要精细化权限管理的应用场景。 系统后端采用Gin作为Web框架,提供高性能的HTTP服务;使用GORM作为ORM框架,简化数据库操作;集成Casbin实现灵活的权限控制模型。前端基于vue-element-admin模板开发,提供现代化的用户界面和交互体验。系统采用分层架构和模块化设计,确保代码的可维护性和可扩展性。 主要功能包括用户管理、角色管理、权限管理、菜单管理、操作日志等核心模块。用户管理模块支持用户信息的增删改查和状态管理;角色管理模块允许定义不同角色并分配相应权限;权限管理模块基于Casbin实现细粒度的访问控制;菜单管理模块动态生成前端导航菜单;操作日志模块记录系统关键操作,便于审计和追踪。 技术栈方面,后端使用Go语言开发,结合Gin、GORM、Casbin等成熟框架;前端使用Vue.js、Element UI等现代前端技术;数据库支持MySQL、PostgreSQL等主流关系型数据库;采用RESTful API设计规范,确保前后端通信的标准化。系统还应用了单例模式、工厂模式、依赖注入等设计模式,提升代码质量和可测试性。 该权限管理系统适用于企业管理系统、内部办公平台、多租户SaaS应用等需要复杂权限控制的场景。作为毕业设计项目,它提供了完整的源码和论文文档,帮助学生深入理解前后端分离架构、权限控制原理、现代Web开发技术等关键知识点。系统设计规范,代码结构清晰,注释完整,非常适合作为计算机相关专业的毕业设计参考或实际项目开发的基础框架。 资源包含完整的系统源码、数据库设计文档、部署说明和毕
(Kriging_NSGA2)克里金模型结合多目标遗传算法求最优因变量及对应的最佳自变量组合研究(Matlab代码实现)内容概要:本文研究了克里金(Kriging)模型与多目标遗传算法(NSGA-II)相结合的方法,用于求解最优因变量及其对应的最佳自变量组合。通过构建克里金代理模型近似复杂的目标函数,有效降低了计算成本,并利用NSGA-II算法进行多目标优化,实现了在多个相互冲突的目标之间寻找帕累托最优解。文中详细阐述了克里金模型的构建过程、超参数估计方法以及与NSGA-II算法的集成方式,最后通过Matlab代码实现该方法,并应用于实际案例中验证其有效性。; 适合人群:具备一定数学建模和优化理论基础,熟悉Matlab编程,从事工程优化、数据分析或相关领域研究的科研人员及研究生。; 使用场景及目标:①解决高维、非线性、计算代价高昂的多目标优化问题;②在缺乏显式函数表达式的仿真或实验系统中,利用代理模型加速优化进程;③获取最优性能指标(因变量)的同时确定对应的最佳设计参数(自变量组合)。; 阅读建议:建议读者结合文中提供的Matlab代码,深入理解克里金模型的构造与交叉验证方法,掌握NSGA-II算法的关键操作,如非支配排序和拥挤距离计算,并通过实际案例调试程序,加深对代理模型辅助优化流程的整体把握。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值