题意:已知起点、圆、矩形,要求计算从起点开始,经过圆(和圆上任一点接触即可),到达矩形的路径的最短距离。(可以穿过园)。

分析:没什么好的方法,凭感觉圆上的每个点对应最短距离,应该是一个凸函数,用三分来解。不过应该是分成两部分,用两次三分来解。具体原因不明,通过实验只能得出三分必须是针对一个凸函数,很明显,从0~2*pi不是一个凸函数,但同理,0~pi,pi~2*pi也不一定是个凸函数。个人认为,网络上流传的[0,pi][pi,2*pi]这种分法,并不存在合理性。继续思考= =

    另外,直接暴力枚举也是能过的。

错误:分析圆上的点与矩形的位置关系写挫了,虽然现在还是研究不明白到底出了什么问题,应该是边界吧。

 double rec(double x,double y)
{
check();
if(x-xi<eps&&y-yj>eps)
return len(x,y,xi,yj);
else if(x-xi<eps&&y-yi<eps)
return len(x,y,xi,yi);
else if(x-xj>eps&&y-yj>eps)
return len(x,y,xj,yj);
else if(x-xj>eps&&y-yi<eps)
return len(x,y,xj,yj); if(x-xi>eps&&x-xj<eps)
if(y-yj>eps)
return fabs(y-yj);
else if(y-yi<eps)
return fabs(yi-y);
else if(y-yi>eps&&y-yj<eps)
if(x-xi<eps)
return fabs(xi-x);
else if(x-xj>eps)
return fabs(x-xj);
}

错误的写法

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std; const double pi=acos(-1.0);
const double eps=1e-; double sx,sy;
double rx,ry,r;
double xi,yi,xj,yj; double degree()
{
return atan((ry-sy)/(rx-sx));
} double len(double x,double y,double a,double b)
{
return sqrt((x-a)*(x-a)+(y-b)*(y-b));
} void change(double& x,double &y)
{
double p;
p=x;
x=y;
y=p;
} void check()
{
if(xi>xj)
change(xi,xj);
if(yi>yj)
change(yi,yj);
} double rec(double x,double y)
{
double lenx=,leny=;
check();
if(x<xi)
lenx=xi-x;
else if(x>xj)
lenx=x-xj;
if(y<yi)
leny=yi-y;
else if(y>yj)
leny=y-yj;
return sqrt(lenx*lenx+leny*leny);
} double f(double m)
{
double dx=rx+r*cos(m);
double dy=ry+r*sin(m); double len1=len(dx,dy,sx,sy);
double len2=rec(dx,dy); return len1+len2;
} int main()
{
int n;
while(~scanf("%lf%lf",&sx,&sy))
{
if(fabs(sx)<eps&&fabs(sy)<eps)
return ;
scanf("%lf%lf%lf",&rx,&ry,&r);
scanf("%lf%lf%lf%lf",&xi,&yi,&xj,&yj); double l=degree(),r=l+pi;
while(fabs(r-l)>eps)
{
double m1=l+(r-l)/;
double m2=r-(r-l)/;
if(f(m1)<f(m2))
r=m2;
else
l=m1;
}
double l1=l;
l=degree()+pi;r=l+pi;
while(fabs(r-l)>eps)
{
double m1=l+(r-l)/;
double m2=r-(r-l)/;
if(f(m1)<f(m2))
r=m2;
else
l=m1;
}
double l2=l;
printf("%.2f\n",min(f(l1),f(l2)));
}
return ;
}

暴力枚举,奇葩的精度。不过相比较而言,这个算法根据有可信度。

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std; const double INF=1e10;
const double pi=acos(-1.0);
const double eps=1e-; double sx,sy;
double rx,ry,r;
double xi,yi,xj,yj; double len(double x,double y,double a,double b)
{
return sqrt((x-a)*(x-a)+(y-b)*(y-b));
} void change(double& x,double &y)
{
double p;
p=x;
x=y;
y=p;
} void check()
{
if(xi>xj)
change(xi,xj);
if(yi>yj)
change(yi,yj);
} double rec(double x,double y)
{
double lenx=,leny=;
check();
if(x<xi)
lenx=xi-x;
else if(x>xj)
lenx=x-xj;
if(y<yi)
leny=yi-y;
else if(y>yj)
leny=y-yj;
return sqrt(lenx*lenx+leny*leny);
} double f(double m)
{
double dx=rx+r*cos(m);
double dy=ry+r*sin(m); double len1=len(dx,dy,sx,sy);
double len2=rec(dx,dy); return len1+len2;
} int main()
{
int n;
while(~scanf("%lf%lf",&sx,&sy))
{
if(fabs(sx)<eps&&fabs(sy)<eps)
return ;
scanf("%lf%lf%lf",&rx,&ry,&r);
scanf("%lf%lf%lf%lf",&xi,&yi,&xj,&yj); double m=INF;
for(double i=;i<=;i+=0.01)
{
m=min(m,f(i/*pi));
}
printf("%.2f\n",m);
}
return ;
}

hdu 4454 Stealing a Cake(计算几何:最短距离、枚举/三分)的更多相关文章

  1. hdu 4454 Stealing a Cake(三分之二)

    pid=4454" target="_blank" style="">题目链接:hdu 4454 Stealing a Cake 题目大意:给定 ...

  2. hdu 4454 Stealing a Cake (三分)

    Stealing a Cake Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  3. HDU 4454 Stealing a Cake(枚举角度)

    题目链接 去年杭州现场赛的神题..枚举角度..精度也不用注意.. #include <iostream> #include <cstdio> #include <cstr ...

  4. HDU 4454 Stealing a Cake --枚举

    题意: 给一个点,一个圆,一个矩形, 求一条折线,从点出发,到圆,再到矩形的最短距离. 解法: 因为答案要求输出两位小数即可,精确度要求不是很高,于是可以试着爆一发,暴力角度得到圆上的点,然后求个距离 ...

  5. hdu 4454 Stealing a Cake 三分法

    很容易想到三分法求解,不过要分别在0-pi,pi-2pi进行三分. 另外也可以直接暴力枚举…… 代码如下: #include<iostream> #include<stdio.h&g ...

  6. hdu 4454 Stealing a Cake

    简单的计算几何: 可以把0-2*pi分成几千份,然后找出最小的: 也可以用三分: #include<cstdio> #include<cmath> #include<al ...

  7. hdu 4454 Stealing a Cake(三分法)

    给定一个起始点,一个矩形,一个圆,三者互不相交.求从起始点->圆->矩形的最短距离. 自己画一画就知道距离和会是凹函数,不过不是一个凹函数.按与水平向量夹角为圆心角求圆上某点坐标,[0, ...

  8. HDU 4454 - Stealing a Cake(三分)

    我比较快速的想到了三分,但是我是从0到2*pi区间进行三分,并且漏了一种点到边距离的情况,一直WA了好几次 后来画了下图才发现,0到2*pi区间内是有两个极值的,每个半圆存在一个极值 以下是代码 #i ...

  9. HDU - 4454: Stealing a Cake (圆上三分)

    pro:给定一个蛋糕,一个矩阵房子,一只蚂蚁.最开始三者两两相离,问蚂蚁触摸到蛋糕后再触摸矩阵的最短距离.结果保留两位小数,坐标的绝对值<1e4: sol:由于坐标不大,而且精度要求不高,不难想 ...

随机推荐

  1. POJ 2528.Mayor's posters-线段树(成段替换、离散数据、简单hash)

    POJ2528.Mayor's posters 这道题真的是线段数的经典的题目,因为数据很大,直接建树的话肯定不可以,所以需要将数据处理一下,没有接触离散化的时候感觉离散化这个东西相当高级,其实在不知 ...

  2. Codeforces Round #262 (Div. 2) A. Vasya and Socks【暴力/模拟/袜子在可以在合法情况下增加后用几天】

    A. Vasya and Socks time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  3. 2.2多线程(java学习笔记)线程状态及线程操作的相关方法

    一.线程的状态 线程一般具有五种状态,即创建.就绪.运行.阻塞.终止. 它们之间的关系: 二.线程操作相关方法 1.设置和取得线程名称. 如果不设置线程名称,系统会自动分配线程名,一般格式为Threa ...

  4. NOIP 2017 赛后反思 [补档]

    首先写一下比赛的情况: D1: T1: 之前做过类似的题目, 因而知道大致的结论, 迅速完成. T2: 貌似直接模拟就可以了, 涉及到字符串信息提取, 比较麻烦, 因而想放到最后做. T3: 非常简洁 ...

  5. 分享最新申请IDP账号的过程,包含duns申请的分享(2013年6月)

    5月份接到公司要申请开发者账号的任务,就一直在各个论坛找申请的流程,但都是一些09年10年的比较旧的流程,现在都已经不适用了,好不容易找到2012年分享的流程吧,才发现申请过程中少了DUNS编码的步骤 ...

  6. 玩转Nuget服务器搭建(一)

    背景                                                                                      公司项目是分模块进行架构 ...

  7. Delphi TClientDataset查找定位功能

    if CDSUserFunc.Locate('mod_id;res_id', VarArrayOf([UserFunc.MOD_ID, UserFunc.RES_ID]), [loCaseInsens ...

  8. centos7 安装LNMP(php7)之 nginx php-fpm yum安装以及配置文件修改

    PHP7.1.6整体参考 https://www.zhihu.com/question/50615606/answer/145699091 http://www.bubuko.com/infodeta ...

  9. cbuffer padding

    nx glslc float 起始于 内存位置4x0 ,4x1,4x2 ,4x3.... bit float2 起始于 内存位置2x4x0 ,2x4x1,2x4x2 ,2x4x3.... bit fl ...

  10. Linux学习之二-Linux系统的目录结构

    Linux学习之二-Linux系统的目录结构 在Linux的根目录下,有很多的目录,但是需要记住,对于Linux而言,一切皆文件.因此此处的目录也是文件.用ls / 命令就能看到根目录下的各类不同的目 ...