POJ 3608

1.计算P上y坐标值最小的顶点(称为 yminP )和Q上y坐标值最大的顶点(称为 ymaxQ)。

2.为多边形在 yminP 和 ymaxQ 处构造两条切线 LP 和 LQ 使得他们对应的多边形位于他们的右侧。

  此时 LP 和 LQ 拥有不同的方向, 并且 yminP 和 ymaxQ 成为了多边形间的一个对踵点对。

3.计算距离(yminP,ymaxQ) 并且将其维护为当前最小值。

4.顺时针同时旋转平行线直到其中一个与其所在的多边形的边重合。

5.如果只有一条线与边重合, 那么只需要计算“顶点-边”对踵点对和“顶点-顶点”对踵点对距离。 都将他们与当前最小值

比较, 如果小于当前最小值则进行替换更新。如果两条切线都与边重合,那么情况就更加复杂了。如果边“交叠”,也就是

可以构造一条与两条边都相交的公垂线(但不是在顶点处相交), 那么就计算“边-边”距离。 否则计算三个新的“顶点-顶

点”对踵点对距离。 所有的这些距离都与当前最小值进行比较, 若小于当前最小值则更新替换。

6.重复执行步骤4和步骤5, 直到新的点对为(yminP,ymaxQ)。

7.输出最小距离

 

这是求两凸包最短距离的经典算法。但是,不知为什么,我的代码死活过不了。。。T_T

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 using namespace std;
  7 const double eps=0.00000001;
  8 
  9 struct point {
 10     double x,y;
 11 }p[10050],q[10050];
 12 int n,m;
 13 int ansp[10050],ansq[10050],cntp,cntq;
 14 int st[10050],stop;
 15 
 16 bool cmp(point A,point B){
 17     if(A.y<B.y) return true;
 18     else if(A.y==B.y){
 19         if(A.x<B.x) return true;
 20     }
 21     return false;
 22 }
 23 
 24 double dist(point a , point b){
 25     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 26 }
 27 
 28 double multi(point a, point b, point c){
 29     point p1; p1.x=a.x-c.x; p1.y=a.y-c.y;
 30     point p2; p2.x=b.x-c.x; p2.y=b.y-c.y;
 31     return (p1.x*p2.y-p1.y*p2.x);
 32 }
 33 
 34 void forTU(point *pot, int &allVex, int *anp, int &cnt){
 35 //    cout<<allVex<<"all"<<endl;
 36     stop=cnt=0;
 37     st[stop++]=0; st[stop++]=1;
 38     for(int i=2;i<allVex;i++){
 39         while(stop>1&&multi(pot[i],pot[st[stop-1]],pot[st[stop-2]])<=0) stop--;
 40         st[stop++]=i;
 41     }
 42     for(int i=0;i<stop;i++)
 43     anp[cnt++]=st[i];
 44     stop=0;
 45     st[stop++]=allVex-1; st[stop++]=allVex-2;
 46     for(int i=allVex-3;i>=0;i--){
 47         while(stop>1&&multi(pot[i],pot[st[stop-1]],pot[st[stop-2]])<=0) stop--;
 48         st[stop++]=i;
 49     }
 50     for(int i=1;i<stop;i++)
 51     anp[cnt++]=st[i];
 52 //    for(int i=0;i<cnt;i++)
 53 //    cout<<anp[i]<<endl;
 54 //    cout<<endl;
 55 }
 56 
 57 double dotcross(point a,point b, point c){
 58     point p1; p1.x=a.x-c.x; p1.y=a.y-c.y;
 59     point p2; p2.x=b.x-c.x; p2.y=b.y-c.y;
 60     return p1.x*p2.x+p1.y*p2.y;
 61 }
 62 
 63 double pline(point a,point b,point c){
 64     return (fabs(multi(a,b,c)))/(dist(a,b));
 65 }
 66 
 67 double pseg(point a,point b,point c){
 68     if(dotcross(a,c,b)<-eps) return dist(b,c);
 69     if(dotcross(b,c,a)<-eps) return dist(a,c);
 70     return pline(a,b,c);
 71 }
 72 
 73 double paral(point a1,point a2, point b1,point b2 ){
 74     double ans1=min(pseg(a1,a2,b1),pseg(a1,a2,b2));
 75     double ans2=min(pseg(b1,b2,a1),pseg(b1,b2,a2));
 76     return min(ans1,ans2);
 77 }
 78 
 79 int sgn(double x)
 80 {
 81     if(fabs(x) < eps)return 0;
 82     if(x < 0)return -1;
 83     else return 1;
 84 }
 85 
 86 double Get_angle(point a1,point a2,point b1,point b2)
 87 {
 88     point p1; p1.x=a1.x-a2.x; p1.y=a1.y-a2.y;
 89     point p2; p2.x=b1.x-b2.x; p2.y=b1.y-b2.y;
 90     return p1.x*p2.y-p1.y*p2.x;
 91 }
 92 
 93 double slove(point *p, int *ap, int &cp, point *q, int *aq, int &cq){
 94     int sp=0,sq=0;  double tmp;
 95     for(int i=0;i<cq;i++)  //max
 96     if(q[aq[i]].y-eps>q[aq[sq]].y) sq=i;
 97     double res=dist(p[ap[sp]],q[aq[sq]]);
 98     for(int i=0;i<cp;i++){
 99     //    while((tmp=fabs(multi(p[ap[i]],p[ap[i+1]],q[aq[sq]])/2)-fabs(multi(p[ap[i]],p[ap[i+1]],q[aq[(sq+1)%cq]])/2))>eps)
100     //    while(tmp=multi(p[ap[i]],p[ap[i+1]],q[aq[(sq+1)%cq]])-multi(p[ap[i]],p[ap[i+1]],q[aq[sq]])>eps)
101     //    sq=(sq+1)%cq;
102     //    if(tmp<-eps){
103          while(sgn(tmp = Get_angle(p[i],p[(i+1)%cp],q[sq],q[(sq+1)%cq])) < 0 )
104             sq = (sq + 1)%cq;
105         if(sgn(tmp) == 0)
106         res=min(res,pseg(p[ap[i]],p[ap[i+1]],q[aq[sq]]));
107     //    cout<<res<<endl;
108     //    }
109         else{
110         res=min(res,paral(p[ap[i]],p[ap[i+1]],q[aq[sq]],q[aq[(sq+1)%cq]]));
111     //    cout<<res<<endl;
112         }
113     }
114     return res;
115 }
116 
117 
118 int main(){
119     double ans=10000000;
120     while(scanf("%d%d",&n,&m)!=EOF){
121         if(n==0&&m==0) break;
122         for(int i=0;i<n;i++)
123         scanf("%lf%lf",&p[i].x,&p[i].y);
124         for(int i=0;i<m;i++)
125         scanf("%lf%lf",&q[i].x,&q[i].y);
126         sort(p,p+n,cmp);
127         sort(q,q+m,cmp);
128         forTU(p,n,ansp,cntp);
129         forTU(q,m,ansq,cntq);
130         ans=1e99;
131          ans=min(ans,slove(p,ansp,cntp,q,ansq,cntq));  //min,max
132          ans=min(ans,slove(q,ansq,cntq,p,ansp,cntp));
133          printf("%.5lf\n",ans);
134     }
135     return 0;
136 }
View Code

别人的代码:

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>using namespace std;const int N=50000;
const double eps=1e-9;
const double INF=1e99;struct Point
{double x,y;
};Point P[N],Q[N];double cross(Point A,Point B,Point C)
{return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}double dist(Point A,Point B)
{return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}double multi(Point A,Point B,Point C)
{return (B.x-A.x)*(C.x-A.x)+(B.y-A.y)*(C.y-A.y);
}//顺时针排序
void anticlockwise(Point p[],int n)
{for(int i=0;i<n-2;i++){double tmp=cross(p[i],p[i+1],p[i+2]);if(tmp>eps) return;else if(tmp<-eps){reverse(p,p+n);return;}}
}//计算C点到直线AB的最短距离
double Getdist(Point A,Point B,Point C)
{if(dist(A,B)<eps) return dist(B,C);if(multi(A,B,C)<-eps) return dist(A,C);if(multi(B,A,C)<-eps) return dist(B,C);return fabs(cross(A,B,C)/dist(A,B));
}//求一条直线的两端点到另外一条直线的距离,反过来一样,共4种情况
double MinDist(Point A,Point B,Point C,Point D)
{return min(min(Getdist(A,B,C),Getdist(A,B,D)),min(Getdist(C,D,A),Getdist(C,D,B)));
}double Solve(Point P[],Point Q[],int n,int m)
{int yminP=0,ymaxQ=0;for(int i=0;i<n;i++)if(P[i].y<P[yminP].y)yminP=i;for(int i=0;i<m;i++)if(Q[i].y>Q[ymaxQ].y)ymaxQ=i;P[n]=P[0];Q[m]=Q[0];double tmp,ans=INF;for(int i=0;i<n;i++){while(tmp=cross(P[yminP+1],Q[ymaxQ+1],P[yminP])-cross(P[yminP+1],Q[ymaxQ],P[yminP])>eps)ymaxQ=(ymaxQ+1)%m;if(tmp<-eps) ans=min(ans,Getdist(P[yminP],P[yminP+1],Q[ymaxQ]));else         ans=min(ans,MinDist(P[yminP],P[yminP+1],Q[ymaxQ],Q[ymaxQ+1]));yminP=(yminP+1)%n;}return ans;
}int main()
{int n,m;while(cin>>n>>m){if(n==0&&m==0) break;for(int i=0;i<n;i++)cin>>P[i].x>>P[i].y;for(int i=0;i<m;i++)cin>>Q[i].x>>Q[i].y;anticlockwise(P,n);anticlockwise(Q,m);printf("%.5lf\n",min(Solve(P,Q,n,m),Solve(Q,P,m,n)));}return 0;
}

  

转载于:https://www.cnblogs.com/jie-dcai/p/3890912.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

天池 在线编程 聪明的销售(计数+贪心)

文章目录1. 题目2. 解题1. 题目 销售主管的任务是出售一系列的物品&#xff0c;其中每个物品都有一个编号。 由于出售具有相同编号的商品会更容易&#xff0c;所以销售主管决定删除一些物品。 现在她知道她最多能删除多少物品&#xff0c;她想知道最终袋子里最少可以包含多少…

关于计算机书籍的收集与整理(一)

本文来源&#xff1a;https://github.com/pinefor1983/CS-Growing-book 一、程序员技术、管理和认知 1、程序员技术&管理 关于程序员职场晋升&#xff0c;这是我的7点具体建议优秀程序员的7个特点对码农后浪的6点建议程序员百万年薪进阶指南做好技术管理&#xff0c;你必须…

域名状态:运营商设置了客户禁止删除保护?过期域名也不能注册为什么?

有的时候,我们打开一个网站.有的时候打不开.这个时候我们在站长工具里面查询,会有域名状态&#xff1a;运营商设置了客户禁止删除保护信息.这个状态对客户来说还是比较好的&#xff0c;以免客户一不小心把域名删了。域名过期后会依次经过以下几个阶段后才可以注册的&#xff1a…

天池 在线编程 放小球(动态规划)

文章目录1. 题目2. 解题2.1 动态规划1. 题目 n 个桶中小球的个数已知, 可以操作 k 次(每次从桶中取出一个球,或者添加一个球), 每个桶有规定的最大容量 W[i]。 求操作后两相邻桶之间的最大差值的平方的最小值。 n < 100 W[i] < 100样例 1: 输入: 5 6 [1,2,3,4,5] [15,…

关于计算机书籍的收集与整理(二)

本文来源&#xff1a;https://github.com/justjavac/free-programming-books-zh_CN#%E7%9B%AE%E5%BD%95 国外程序员在 stackoverflow 推荐的程序员必读书籍&#xff0c;中文版。stackoverflow 上的程序员应该阅读的非编程类书籍有哪些&#xff1f; 中文版github 上的一个流行的…

LeetCode 1716. 计算力扣银行的钱(等差数列)

文章目录1. 题目2. 解题1. 题目 Hercy 想要为购买第一辆车存钱。他 每天 都往力扣银行里存钱。 最开始&#xff0c;他在周一的时候存入 1 块钱。 从周二到周日&#xff0c;他每天都比前一天多存入 1 块钱。 在接下来每一个周一&#xff0c;他都会比 前一个周一 多存入 1 块钱…

互联网产品 从设计到运营 这中间提高须要关注的站点

互联网产品 从设计到运营 这中间提高须要关注的站点 https://github.com/edagarli/resourcecollects 转载于:https://www.cnblogs.com/mengfanrong/p/3897858.html

整理与总结Python关于对文件的操作

一、前言 python中对文件、文件夹&#xff08;文件操作函数&#xff09;的操作需要涉及到os模块和shutil模块 二、操作命令 得到当前工作目录&#xff0c;即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir() 函数用来删除一个文…

LeetCode 1717. 删除子字符串的最大得分

文章目录1. 题目2. 解题374 / 1631&#xff0c;前22.9%1215 / 7873&#xff0c;前15.4%1. 题目 给你一个字符串 s 和两个整数 x 和 y 。你可以执行下面两种操作任意次。 删除子字符串 "ab" 并得到 x 分。 比方说&#xff0c;从 “cabxbae” 删除 ab &#xff0c;得…

利用Python把四张图片按照顺序拼接起来

一、需求&#xff1a; 给出四张图片&#xff0c;按照一定的顺序拼接起来 二、图片&#xff1a; 左上角&#xff1a;&#xff08;像素512*512&#xff09; 右上角&#xff1a;&#xff08;像素284*512&#xff09; 左下角&#xff1a;&#xff08;像素284*512&#xff09; 右…

证券总结

1.暴涨之后&#xff0c;如果没有阳线助涨&#xff0c;则可能跌&#xff0c;也可能震荡&#xff0c;看下一个交易日的状况定夺;暴跌类似。 2.持续小规模阳线&#xff0c;最后稍大阳线&#xff0c;但非暴涨。此时如果下一交易日阴线极有可能是短暂小幅回调&#xff0c;莫做空&…

Linux:文件创建时间如何修改?

一、需求 修改文件创建时间 二、知识及方法步骤 touch命令用于创建空白文件或修改文件时间。 在Linux系统中一个文件有三种时间&#xff1a; 更改内容的时间 - mtime&#xff1a;当文件进行被写的时候&#xff0c;CTime就会更新更改权限的时间 - ctime&#xff1a;当文件的…

面向对象学习笔记

abstract:抽象类或方法的关键字注意事项&#xff1a;一个类中至少有一个抽象方法不允许有大括号主要意义就是规范方法&#xff0c;要求必须按照抽象中的方法来写继承抽象类的类&#xff0c;必须重载完全抽象类的方法抽象类是不能被实例化的&#xff0c;因为本身没有意义 extend…

小案例:编写立方体六个面,合成一张全景图后端

一、需求&#xff1a; 给出立方体六个面&#xff0c;合成一张全景图 二、主要知识&#xff1a;py360convert 2.1、该项目的特点&#xff1a; 立方体贴图和等矩形之间的转换 等角于平面 纯python实现&#xff0c;仅依赖于numpy和scipy矢量化实施&#xff08;在大多数地…

LeetCode 1721. 交换链表中的节点(快慢指针)

文章目录1. 题目2. 解题1. 题目 给你链表的头节点 head 和一个整数 k 。 交换 链表正数第 k 个节点和倒数第 k 个节点的值后&#xff0c;返回链表的头节点&#xff08;链表 从 1 开始索引&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2 输出&am…

[Python] NotImplemented 和 NotImplementedError 区别

NotImplemented 是一个非异常对象&#xff0c;NotImplementedError 是一个异常对象。 >>> NotImplemented NotImplemented >>> NotImplementedError <type exceptions.NotImplementedError>>>> type(NotImplemented) <type NotImplemented…

爬虫小案例:基于Bing关键词批量下载图片

一、需求&#xff1a; 基于Bing网站&#xff0c;输入关键词&#xff0c;批量下载图片保存到本地 二、演示&#xff1a; 三、直接上代码 import os import urllib.request import urllib.parse from bs4 import BeautifulSoup import re import time# 设置请求头 header {Us…

LeetCode 1722. 执行交换操作后的最小汉明距离(并查集)

文章目录1. 题目2. 解题1. 题目 给你两个整数数组 source 和 target &#xff0c;长度都是 n 。 还有一个数组 allowedSwaps &#xff0c;其中每个 allowedSwaps[i] [ai, bi] 表示你可以交换数组 source 中下标为 ai 和 bi&#xff08;下标从 0 开始&#xff09;的两个元素。…

线性表的顺序表示和实现

/* 顺序表存储结构容易实现随机存取线性表的第i 个数据元素的操作&#xff0c;但在实现插入、 删除的操作时要移动大量数据元素&#xff0c;所以&#xff0c;它适用于数据相对稳定的线性表&#xff0c;如职工工资 表、学生学籍表等。 c2-1.h 是动态分配的顺序表存储结构&#x…

爬虫小案例:基于Bing关键词批量下载图片(第二版)

一、需求&#xff1a; 基于Bing网站&#xff0c;输入关键词&#xff0c;批量下载图片保存到本地 二、代码展示&#xff1a; import requests from lxml import etree import os from multiprocessing.dummy import Pool import json from time import time# 作用&#xff1a…