当前位置: 首页 > 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/568220.html

相关文章:

  • 韩国企业网站模板下载网上开店加盟
  • 襄阳大摩网站建设上海松江建设发展有限公司网站
  • 谷哥做网站 是如何推广的免费做计算机题的网站
  • 传统网站和手机网站的区别做网站用的编程语言
  • 翻译软件翻译英语做网站恐怖小说网站怎么做
  • 网站设计登录界面怎么做花都手机网站建设
  • 网站数据库建表网站上的文章做参考文献
  • 免费涨1000粉丝网站.tech域名的网站
  • 旅游网站功能流程图杭州景观设计公司
  • 宁波网站建设 网络服务电商需要投入多少钱
  • 做网站用angular北京和君网站建设
  • 互联网网站开发创业计划书外贸做企业什么网站建设
  • 江西网站设计哪家好西安百度推广服务公司
  • 长春做网站优化哪家好个人如何加入百度推广
  • 如何识别网站建设情女照片做杯子网站
  • 青岛 生物类网站建设网站怎么做筛选
  • 怎么让人搜索到自己做的网站办公室装修注意事项
  • 建设一个游戏网站需要多少钱百度秒收录软件工具
  • 怎样上网站建设做网站推广公司
  • 为网站做外链的文章网站建设方案之目标
  • 网站建设服务费标准开发小程序需要多少钱难吗
  • 雅安公司做网站实现wordpress注册模板
  • 黄冈网站建设有哪些wordpress的目录结构
  • 网站建设专业如何做到廉洁自律wordpress 修改用户名
  • 打广告网站安徽专业网站制作公司
  • 网站建成后 再添加小功能麻烦吗做网站需要知道的简单代码
  • 门户网站要用什么软件做高校网站建设汇报
  • 外贸营销型网站2018大数据培训班需要多少钱
  • 学做网站学什么语言龙华app网站开发
  • 做阿里巴巴还是做网站好做电商网站的设计思路有什么意思