[POJ1113&POJ1696]凸包卷包裹算法和Graham扫描法应用各一例

  凸包的算法比较形象好理解 代码写起来也比较短 所以考前看一遍应该就没什么问题了。。>_<



POJ1113

  刚开始并没有理解为什么要用凸包,心想如果贴着城堡走不是更好吗?

  突然发现题目中有要求在满足把所有点包括在内的情况下周长最短...这不就是凸包的性质吗?

  而且显然如果城堡是凹的话,往里面绕一圈肯定会使周长增加...

  然后可以从简单的三角形四边形推广出去,发现每个拐角-左右各90度之后所有的加和为180度

  也就是在城堡周长的基础上再加一个半径为L的圆周长即是所求答案。

  上次的模板写错了...应该是快排部分没有处理好...这次重新写的时候才发现...

program poj1113;
const pi=3.14159265358979;maxn=1010;
type point=record x,y:longint;end;
var i,n,l,len:longint;
     ans:extended;
     a:array[-1..maxn]of point;
     dis:array[-1..maxn]of int64;
     stack:array[-1..maxn]of point;

function getdis(a,b:point):int64;
begin
    exit(sqr(a.x-b.x)+sqr(a.y-b.y));
end;

function cross(p0,p1,p2:point):int64;
begin
    exit((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
end;

procedure qsort(L,R:longint);
var i,j,mid:longint;
      midy:int64;
      midx:point;
begin
    i:=L;j:=R;mid:=random(R-L+1)+L;
    midx:=a[mid];midy:=dis[mid];
    repeat
        while (i<R)and((cross(a[1],a[i],midx)>0)or((cross(a[1],a[i],midx)=0)and(dis[i]<midy))) do inc(i);
        while (L<j)and((cross(a[1],a[j],midx)<0)or((cross(a[1],a[j],midx)=0)and(dis[j]>midy))) do dec(j);
        if i<=j then
        begin
            a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
            dis[0]:=dis[i];dis[i]:=dis[j];dis[j]:=dis[0];
            //之前的模板这里的dis数组没有交换,那道题是平面最远点对的...就导致取错了点。
            inc(i);dec(j);
        end;
    until i>j;
    if i<R then qsort(i,R);
    if L<j then qsort(L,j);
end;

procedure Graham(n:longint;var len:longint);
var k,i:longint;
begin
    k:=0;a[0].x:=maxlongint;a[0].y:=maxlongint;
    for i:=1 to n do
    if (a[i].y<a[k].y)or((a[i].y=a[k].y)and(a[i].x<a[k].x)) then k:=i;
    a[0]:=a[1];a[1]:=a[k];a[k]:=a[0];
    for i:=2 to n do dis[i]:=getdis(a[i],a[1]);
    qsort(2,n);
    len:=3;stack[1]:=a[1];stack[2]:=a[2];stack[3]:=a[3];
    for i:=4 to n do
    begin
        while cross(stack[len-1],a[i],stack[len])>=0 do dec(len);
        //要求边上的点也取的话就不能加等号
        inc(len);stack[len]:=a[i];
    end;
end;

begin
    //assign(input,‘poj1113.in‘);reset(input);
    readln(n,l);
    for i:=1 to n do readln(a[i].x,a[i].y);
    Graham(n,len);
    ans:=sqrt(getdis(stack[1],stack[len]));
    //累计周长不能忘了第一个点和第n个点之间的边
    //这里虽然容易检查出来但是希望下次累计长度的时候还是不要忘。。>_<
    for i:=2 to len do ans:=ans+sqrt(getdis(stack[i],stack[i-1]));
    writeln(ans+2*pi*l:0:0);
end.


POJ1696

  人生多艰...

  话说好像还把在我后面评测的同学影响成了CE...QAQ 

  这道题只要不停地取满足条件的对于当前点最右边的点,当然要保证当前点右拐没有没取过的点。

  首先肯定是都可以取到的,然后用卷包裹不停地取就好了...

  这题唯一需要修改的就是取过的点要打标记,然后就轻松AC啦~

program poj1696;
const maxn=55;
type point=record x,y,id:longint;end;
var t,test,i,n:longint;
      a:array[-1..maxn]of point;
      vis:array[-1..maxn]of boolean;
      s:point;

function cross(p0,p1,p2:point):longint;
begin
    exit((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
end;

function getdis(a,b:point):longint;
begin
    exit(sqr(a.x-b.x)+sqr(a.y-b.y));
end;

procedure Wrap(s:point);
var i,j,k:longint;
begin
    fillchar(vis,sizeof(vis),true);
    write(n,‘ ‘);
    for i:=1 to n do
    begin
        for j:=1 to n do if vis[j] then begin k:=j;break;end;
        // 刚开始TOO NAIVE...给k的初值赋为0,然后0节点搞了个(0,1000),后来发现这满足刚开始的条件QAQ
        // 为了维护世界的和平...还是尽量不要用没有出现过的点好了...
        for j:=1 to n do if (vis[j])and((cross(s,a[j],a[k])>0)or((cross(s,a[j],a[k])=0)and(getdis(a[j],s)<getdis(a[k],s)))) then k:=j;
        write(a[k].id,‘ ‘);s:=a[k];vis[k]:=false;
    end;
end;

begin
    //assign(input,‘poj1696.in‘);reset(input);
    readln(test);
    for t:=1 to test do
    begin
        readln(n);s.x:=0;s.y:=maxlongint;
        for i:=1 to n do
        begin
            readln(a[i].id,a[i].x,a[i].y);
            if a[i].y<s.y then s.y:=a[i].y;
        end;
        Wrap(s);writeln;
    end;
end.
时间: 2024-10-06 07:32:55

[POJ1113&POJ1696]凸包卷包裹算法和Graham扫描法应用各一例的相关文章

POJ 1113 Wall 卷包裹法求凸包

Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 31199   Accepted: 10521 Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's castle. The King was so greedy, that he w

(模板)poj1113(graham扫描法求凸包)

题目链接:https://vjudge.net/problem/POJ-1113 题意:简化下题意即求凸包的周长+2×PI×r. 思路:用graham求凸包,模板是kuangbin的. AC code: #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn=1005; const double PI=

POJ 1696 Space Ant 卷包裹法

Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3316   Accepted: 2118 Description The most exciting space discovery occurred at the end of the 20th century. In 1999, scientists traced down an ant-like creature in the planet Y19

uva 1340 - Find the Border(卷包裹)

题目链接:uva 1340 - Find the Border 模仿别人代码写的卷包裹算法.就是沿着折线的外围走一圈,每次到一个新的点需要转弯时转向向右拐最多的那条. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <complex> #include <algorithm> using namespace std; ty

[hdu contest 2019-07-29] Azshara&#39;s deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相交但是可以有公共端点. 首先找出凸包,然后把n*n条边和m个圆算点到直线距离验证一下边是否与圆相交存到e[n][n]里. 然后显然是一个dp,但是我开始看错题目了以为不能有公共端点,能有公共端点的情况考虑一下像一个找三角形的过程,就是区间dp. 区间dp有一点妙的地方是最大区间范围是凸包点数而不用+1,因为连

最小生成树 Prim(普里姆)算法和Kruskal(克鲁斯特尔)算法

Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小.该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现:并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现:1959年,艾兹格·迪科斯彻再次发现了该算法.因此,在某些场

使用Apriori算法和FP-growth算法进行关联分析(Python版)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

Dijkstra算法和Floyed算法

写的比较好的三篇文章 Floyed算法 最短路径-Dijkstra算法和Floyed算法 最短路径之Dijkstra算法和Floyed算法 哈哈,他山之石,可以攻玉 自己有心得,慢慢补充