当前位置: 首页 > wzjs >正文

自己可以建个免费网站吗制作静态动漫网站模板

自己可以建个免费网站吗,制作静态动漫网站模板,广西省建设厅网站,制作公司网页代码前置了解: Andrew算法(求凸包)-CSDN博客 旋转卡壳 (Rotating Calipers)算法是一种用于解决凸包相关问题的高效算法,尤其适用于计算凸包直径(即凸包上任意两点间的最大距离)、最小包…

前置了解:

 Andrew算法(求凸包)-CSDN博客

旋转卡壳

(Rotating Calipers)算法是一种用于解决凸包相关问题的高效算法,尤其适用于计算凸包直径(即凸包上任意两点间的最大距离)、最小包围矩形等问题 

旋转卡壳算法的核心思想是:通过一对平行线(卡壳)“夹住” 凸包,并旋转这对平行线,在旋转过程中枚举所有可能的对踵点对(即凸包上距离最远的点对),从而找到凸包的直径。 

1. 对踵点对(Antipodal Pairs)
  • 定义:如果过凸包上的两个点可以作一对平行切线,使得凸包夹在这两条平行线之间,则称这两个点为一对对踵点。
  • 性质:凸包的直径一定是某一对对踵点之间的距离。因此,只需要枚举所有对踵点对,计算它们之间的距离,取最大值即可。
2. 旋转过程
  • 边 - 点对:对于凸包上的每条边,找到距离该边最远的点。这个点和边的两个端点构成潜在的对踵点对。
  • 旋转对称性:当一条边对应的最远点确定后,随着边按顺序旋转,对应的最远点也会按顺序移动(不会回溯),因此可以在线性时间内枚举所有对踵点对。

 

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;

struct vec{
    double x,y;
    bool operator<(const vec& other) const {
        if(x != other.x) return x < other.x;
        return y < other.y;
    }
};//凸包:比较函数

vec p[N], st[N];

double cross(vec A, vec B){
    return A.x*B.y-A.y*B.x; 
}//凸包,叉乘函数

double Side(vec a, vec b, vec p)  {
    vec A={b.x-a.x, b.y-a.y}; 
    vec B={p.x-a.x, p.y-a.y}; 
    return cross(A,B);
}//凸包,根据3点两向量叉乘求左右

double dis2(vec a, vec b) {
    return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}//答案,平方距离

int Andrew(int n) {
    if(n == 0) return 0;
    
    sort(p+1, p+n+1);
    
    int top = 0;
    
    // 构建下凸
    for(int i=1; i<=n; i++){
        while(top >= 2 && Side(st[top-2], st[top-1], p[i]) <= 0)
            top--;
        st[top++] = p[i];
    }
    
    int temp = top;
 
    // 构建上凸
    for(int i=n-1; i>=1; i--){
        while(top > temp && Side(st[top-2], st[top-1], p[i]) <= 0)
            top--;
        st[top++] = p[i];
    }
    
    // 如果只有一个点,凸包就是这个点本身
    if(n == 1) return 1;
    
    // 如果有两个点,凸包就是这两个点
    if(n == 2) return 2;
    
    // 移除重复的起点
    if(top > 1) top--;
    
    return top;
}

double rotating_calipers(int n){/核心转圈圈
    if(n < 2) return 0;
    if(n == 2) return dis2(st[0], st[1]);//12特判
    
       double res = 0;
    int j = 1;  // 初始化最远点为 st[1]
    
            // 枚举每条边 st[i] - st[i+1]
    for(int i=0; i<n; i++){
        // 找到边 st[i]-st[i+1] 对应的最远点 st[j]
        while(Side(st[i], st[(i+1)%n], st[j]) < Side(st[i], st[(i+1)%n], st[(j+1)%n]))//n只是为了防首尾那一个点
            j = (j+1)%n;
        
        // 更新最大距离
        res = max(res, max(dis2(st[i], st[j]), dis2(st[(i+1)%n], st[j])));
        
        // 检查对踵点对 (i, j+1) 和 (i+1, j+1)
        res = max(res, max(dis2(st[i], st[(j+1)%n]), dis2(st[(i+1)%n], st[(j+1)%n])));/直接线性了!!
    }
    
    return res;
}

int main(){
    int n;
    cin >> n;
    
    for(int i=1; i<=n; i++){
        cin >> p[i].x >> p[i].y;
    }
    
    int m = Andrew(n);
    
    cout << fixed << setprecision(0) << rotating_calipers(m) << endl;
    
    return 0;
}

题目2

 很明显,对踵点对他又要发挥作用惹

以下代码只有黑色部分与上面不同

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;

struct vec{
    double x,y;
    bool operator<(const vec& other) const {
        if(x != other.x) return x < other.x;
        return y < other.y;
    }
};

vec p[N], st[N];

double cross(vec A, vec B){
    return A.x*B.y-A.y*B.x; 
}

double Side(vec a, vec b, vec p)  {
    vec A={b.x-a.x, b.y-a.y}; 
    vec B={p.x-a.x, p.y-a.y}; 
    return cross(A,B);
}

double dis2(vec a, vec b) {
    return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}//没用,只不过没有删

int Andrew(int n) {
    if(n == 0) return 0;
        sort(p+1, p+n+1);  
    int top = 0;
    for(int i=1; i<=n; i++){
        while(top >= 2 && Side(st[top-2], st[top-1], p[i]) <= 0)
            top--;
        st[top++] = p[i];
    }
    int temp = top;
    for(int i=n-1; i>=1; i--){
        while(top > temp && Side(st[top-2], st[top-1], p[i]) <= 0)
            top--;
        st[top++] = p[i];
    }   
    if(n == 1) return 1;   
    if(n == 2) return 2;    
    if(top > 1) top--;   
    return top;
}

double rotating_calipers(int n){
    double ans=0;
    for (int i=1;i<n;i++){
        int a=i,b=i+1;

        for (int j=i+1;j<=n;j++){

//众所周知,叉乘是两向量的对应平行四边形的面积。。。。。。


            while (Side(st[i],st[j],st[a+1])<Side(st[i],st[j],st[a])) a=a%n+1;//这里的上面为什么是小于号:原因:在该算法中,我们其实要遍历每条对角线,也就是i-j线,假设j现在离i比较远,由于a初始是i,很明显加1之后i-a在i-j的右边,叉积是负数。。。。。所以<才对;;而b为什么又需要大于呢?根据已有的j=i+1;很明显从一开始,b+1的点一定是要大于b点(0),所以从一开始,b就被推到了i-j的上面,也就是左侧,,,很明显成为了正数;然后对于一条对角线,很明显我们需要在他的左右侧各找一个最大三角形来围最后的最大四边形。。完美!


            while (Side(st[i],st[j],st[b+1])>Side(st[i],st[j],st[b])) b=b%n+1;//主要还是加1,%n还是为了防止那个首尾连接点。。作用:通过不断迭代,找到选择了当前边i=1,j=i+1的最大面积;之后因为ab已经++,不会回溯,就是开始逆时针转圈圈了(i大循环是会回溯的)
            ans=max(ans,-Side(st[i],st[j],st[a])+Side(st[i],st[j],st[b]));
        }
    }
    return ans/2;
}

int main(){
    int n;
    cin >> n;
    
    for(int i=1; i<=n; i++){
        cin >> p[i].x >> p[i].y;
    }
    
    int m = Andrew(n);
    
    cout << fixed << setprecision(3) << rotating_calipers(m) << endl;
    
    return 0;
}

http://www.dtcms.com/wzjs/585325.html

相关文章:

  • 什么是网站镜像浙江室内设计公司排名
  • 网站建设 提供源码企查查企业信息查询网页版
  • 过界女主个人做网站的网站单页支付宝支付怎么做的
  • 网站建设包含图文设计深圳住房和建设局网站全景看房
  • 建设部网站官工程质量手册wordpress提工单
  • wordpress 改网站介绍wordpress下载整站源码
  • 网站建设流程与构架漯河市建设监理协会网站
  • 福建省建设资格注册与管理中心网站北京工商登记服务平台
  • wordpress主题如何导入演示关键词首页排名优化平台
  • 成都网站开发的公司网站后台上传图片步骤
  • 免费发布项目的网站网站做实名验证码
  • 如何seo网站挣钱引流推广方式
  • 建设一个游戏网站需要多少钱做餐厅网站的需求分析
  • 在线商城网站制作网站建设制作设计seo优化湖北
  • 网站要做几个备案手机网站自适应宽度
  • 用r做简易的网站互联网项目招商加盟
  • 网站中页面模板设计顺德手机网站设计信息
  • 做外卖网站制作网站开发用的图片
  • 网站文章更新注意什么网站买空间的价格
  • 房地产公司的网站建设方案常州网站建设 光龙
  • 腾讯云网站建设视频教程wordpress安装目录权限设置
  • 长沙十大景点排名优化方案
  • 可以在几个 网站备案网站改版 信科网络
  • 比特币网站建设做网站商城互联网公司
  • 外贸网站建设有哪些要求wordpress 价格
  • 仙居制作网站搭建平台聚合力
  • 南昌做网站比较好的公司有哪些做网站 南京
  • 网站流量统计实现深圳百度关键词排名
  • 深圳网站设计服务商购物网站大全
  • 云南省城乡建设培训中心网站网站后台上传不了文件