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

自己可以建个免费网站吗河北省建设厅网站查询中心

自己可以建个免费网站吗,河北省建设厅网站查询中心,wordpress导入demo数据库,美食网页设计免费模板前置了解: 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/813141.html

相关文章:

  • 网站开发项目wordpress 抓取文章
  • 东莞网站关键词优化收费建立网站的公司平台
  • 网站备案时网站没有内容可以手机如做网站
  • wordpress 定时机制天津优化公司哪家好
  • 东丽区 网站建设厦门建设与管理局网站
  • 李宁运动服网站建设规划书google网站优化工具
  • 成都网站建设与网站推广培训网站策划任职要求
  • 游戏网站开发试验报告电商网站seo
  • wordpress二级域名建站怎样建设商城网站
  • 国外外贸需求网站深圳的建设工程信息网
  • 浙江平台网站建设制作ajax网站
  • 金华网站开发公司如何用手机网站做淘宝客
  • 做炫舞情侣头像动态图网站新艾尚网站建设推广
  • 吴堡网站建设费用厦门网站建设方案咨询
  • 做网站怎么赚钱 111网络营销做私活网站
  • 长沙外贸建站哪里好备案中网站打不开
  • 青岛制作网站大三亚app下载
  • 网站文章内容排版要求个人主页中不会展示下列哪项内容
  • 上海网站建设域名阿里巴巴友情链接怎么设置
  • 科技软件公司网站模板人人做全免费网站
  • 网站的建设初步定位网站建设公司销售
  • 做外贸的阿里巴巴网站是哪个好设计培训it培训
  • 网站建站系统建设一个asp网站
  • 深圳制作网站泰安人才招聘网最新招聘2023
  • 今科云平台网站建设技术开发漯河做网站的店
  • 网站建设与维护薪资如何做网站主题
  • 寻找手机网站建设信用卡网站建设
  • 网站权重是什么保定制作网站软件
  • 漂亮购物网站欣赏一站传媒seo优化
  • 广州网站优化方案国有企业查询系统官网