【poj3608】 Bridge Across Islands

http://poj.org/problem?id=3608 (题目链接)

题意:求两凸包间最短距离

Solution 
  难写难调,旋转卡壳,还真是卡死我了。 
  先分别选出两凸包最上点和最下点,从这两点开始向逆时针方向旋转卡壳。用叉乘判断是否旋转旋转,具体操作跟求凸包直径差不多。

poj discuss蒯下来的数据制造器:

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;

struct point{double x,y;};
struct polygon
{
    int n;
    point data[10];
};
#define N   16
polygon p[N]={
    {4,{{0,0},{-1,0},{-1,-1},{0,-1}}},
    {4,{{2,0},{2,-1},{3,-1},{3,0}}},
    {4,{{247,208},{247,235},{375,235},{375,208}}},
    {3,{{85 ,101},{116 ,168},{168 ,103}}},
    {3,{{131 ,189},{216 ,148},{196 ,209}}},
    {3,{{180 ,127},{246 ,127},{202 ,144}}},
    {3,{{226 ,201},{297 ,201},{242 ,151}}},
    {3,{{42 ,225},{61 ,261},{100,222}}},
    {3,{{84 ,261},{99 ,246},{102,260}}},
    {3,{{72,309},{157,224},{167,309}}},
    {3,{{170,221},{229,221},{199,245}}},
    {3,{{190,90},{153,47},{225,108}}},
    {3,{{165,230},{168,242},{172,233}}},
    {6,{{143,146},{133,156},{138,170},{150,173},{161,166},{161,152}}},
    {5,{{109,208},{100,236},{111,253},{122,250},{161,206}}},
    {6,{{177,273},{174,309},{202,377},{417,375},{490,270},{268,239}}}
    };
int main()
{
    srand(time(NULL));
    //freopen("aaa.in","w",stdout);
    int i=0,j=0,k,num=0;
    while (i==j) i=rand()%N,j=rand()%N;
    num++;
    //if(num>35||num<=33)continue;
    printf("%d %d\n",p[i].n,p[j].n);
    for(k=0;k<p[i].n;k++)
        printf("%lf %lf\n",p[i].data[k].x,p[i].data[k].y);
    for(k=0;k<p[j].n;k++)
        printf("%lf %lf\n",p[j].data[k].x,p[j].data[k].y);
    printf("0 0\n");
    return 0;
}

代码:

// poj3608
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#define esp 1e-8
#define inf 2147483640
#define LL long long
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {
    LL x=0,f=1;char ch=getchar();
    while (ch>‘9‘ || ch<‘0‘) {if (ch==‘-‘) f=-1;ch=getchar();}
    while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}

const int maxn=10010;
struct point {
    double x,y;
    point() {};
    point (double _x,double _y):x(_x),y(_y){}
    friend point operator - (const point &a,const point &b) {
        point x;
        x.x=a.x-b.x;x.y=a.y-b.y;
        return x;
    }
}p1[maxn],p2[maxn],p0;
int sn[maxn],sm[maxn],n,m;

double cross(point p0,point p1,point p2) { //叉乘
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double dis(point a,point b) { //点a与点b之间的距离
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b) { //极角排序
    double t=cross(p0,a,b);
    if (t<0) return 0;
    if (t>0) return 1;
    return dis(p0,a)<dis(p0,b);
}
int dcmp(double x) { //double比较
    return fabs(x)<esp ? 0 : (x>0 ? 1 : -1);
}
int Graham(int n,point *p) { //求凸包
    int k=1,top=2;
    for (int i=2;i<=n;i++)
        if (p[i].x==p[k].x ? p[i].y<p[k].y : p[i].x<p[k].x) k=i;
    p0=p[k];p[k]=p[1];p[1]=p0;
    sort(p+2,p+1+n,cmp);
    for (int i=3;i<=n;i++) {
        while (top>1 && cross(p[top-1],p[top],p[i])<=0) top--;
        p[++top]=p[i];
    }
    return top;
}
double pldis(point a,point b,point c) { //点a到线段bc的最短距离
    point s(a-b),t(c-b);
    if (s.x*t.x+s.y*t.y<0) return dis(a,b);
    s=(a-c);t=(b-c);
    if (s.x*t.x+s.y*t.y<0) return dis(a,c);
    return fabs(cross(a,b,c))/dis(b,c);
}
double lldis(point a,point b,point c,point d) { //线段ab与线段cd的最短距离
    return min(min(pldis(a,c,d),pldis(b,c,d)),min(pldis(c,a,b),pldis(d,a,b)));
}
double RC(point *pl,point *pr,int p,int q,int n,int m) { //旋转卡壳
    double tmp,minl=1e90;
    pl[n+1]=pl[1];pr[m+1]=pr[1];
    for (int i=1;i<=n;i++) {
        while ((tmp=cross(pl[p+1],pr[q+1],pl[p])-cross(pl[p+1],pr[q],pl[p]))>esp) q=q%m+1;
        if (tmp<-esp) minl=min(minl,pldis(pr[q],pl[p],pl[p+1]));
        else minl=min(minl,lldis(pl[p],pl[p+1],pr[q],pr[q+1]));
        p=p%n+1;
    }
    return minl;
}
void clocksort() { //逆时针排序
    p0.x=0;p0.y=0;
    for (int i=1;i<=n;i++) {p0.x+=p1[i].x;p0.y+=p1[i].y;}
    p0.x/=n;p0.y/=n;
    sort(p1+1,p1+1+n,cmp);
    p0.x=0;p0.y=0;
    for (int i=1;i<=m;i++) {p0.x+=p2[i].x;p0.y+=p2[i].y;}
    p0.x/=m;p0.y/=m;
    sort(p2+1,p2+1+m,cmp);
}
int main() {
    while (scanf("%d%d",&n,&m)!=EOF && n && m) {
        for (int i=1;i<=n;i++) scanf("%lf%lf",&p1[i].x,&p1[i].y);
        for (int i=1;i<=m;i++) scanf("%lf%lf",&p2[i].x,&p2[i].y);
        n=Graham(n,p1);
        m=Graham(m,p2);
        //clocksort();
        int l=1,r=1;
        for (int i=1;i<=n;i++) if (dcmp(p1[i].y-p1[l].y)<0) l=i; //最下点
        for (int i=1;i<=m;i++) if (dcmp(p2[i].y-p2[r].y)>0) r=i; //最上点
        printf("%.5lf\n",min(RC(p1,p2,l,r,n,m),RC(p2,p1,r,l,m,n)));
    }
    return 0;
}

  

时间: 2024-08-18 04:47:55

【poj3608】 Bridge Across Islands的相关文章

【POJ 3608】Bridge Across Islands

Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8853   Accepted: 2603   Special Judge Description Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory

【LeetCode】Number of Islands 解题报告

[题目] Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounde

【LeetCode】Number of Islands

Number of Islands 问题描述 Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid

【BZOJ2095】【POI2010】Bridge 网络流

题目大意 ? 给你一个无向图,每条边的两个方向的边权可能不同.要求找出一条欧拉回路使得路径上的边权的最大值最小.无解输出"NIE". \(2\leq n\leq 1000,1\leq m\leq 2000\) 题解 ? 我们先二分答案\(ans\),把边权大于\(ans\)的边删掉. ? 现在图中还剩下一些有向边和一些无向边,也就是说这是一个混合图. ? 混合图的欧拉回路怎么求? ? 先把无向边定向(方向任意),求出每个点的出度\(d1_i\)和入度\(d2_i\).如果存在点\(i\

【LeetCode】深搜DFS(共85题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [98]Validate Binary Search Tree [99]Recover Binary Search Tree [100]Same Tree [101]Symmetric Tree [104]Maximum Depth of Binary Tree [105]Construct Binary Tree from Preorder and Inorder

【LeetCode】BFS(共43题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [101]Symmetric Tree 判断一棵树是不是对称. 题解:直接递归判断了,感觉和bfs没有什么强联系,当然如果你一定要用queue改写的话,勉强也能算bfs. // 这个题目的重点是 比较对象是 左子树的左儿子和右子树的右儿子, 左子树的右儿子和右子树的左儿子.不要搞错. // 直接中序遍历的话会有错的情况,最蠢的情况是数字标注改一改.. 1 /** 2

【LeetCode】并查集 union-find(共16题)

链接:https://leetcode.com/tag/union-find/ p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [128]Longest Consecutive Sequence  (2018年11月22日,开始解决hard题) 给了一个无序的数组,问这个数组里面的元素(可以重新排序)能组成的最长的连续子序列是多长.本题的时间复杂度要求是 O(N). 本题 array 专题里面有, 链接:https

LeetCode | 0200. Number of Islands岛屿数量【Python】

LeetCode 0200. Number of Islands岛屿数量[Medium][Python][DFS] Problem LeetCode Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or v

【反射】Class Field Method Constructor

Class public final class java.lang.Class<T> extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement 类型参数 T:由此 Class 对象建模的类的类型.例如, String.class 的类型是 Class<String>.如果将被建模的类未知,则使用 Class<?>. Instances of the class