hdu 6097 Mindis
2017-08-10 23:08
309 查看
传送门
题意:
圆心 O 坐标(0, 0), 给定两点 P, Q(不在圆外),满足 PO = QO,
要在圆上找一点 D,使得 PD + QD 取到最小值。
此题会补充三种做法:
1.椭圆
平面内与两定点
、
的距离的和等于常数
(
)的动点P的轨迹叫做椭圆,即:
椭圆平面内到定点
(c,0)的距离和到定直线
:
(
不在
上)的距离之比为常数
(即离心率
,0<e<1)的点的轨迹是椭圆。
其中定点
为椭圆的焦点[5] ,定直线
称为椭圆的准线(该定直线的方程是
(焦点在x轴上),或
(焦点在y轴上))。
其他定义
根据椭圆的一条重要性质:椭圆上的点与椭圆长轴(事实上只要是直径都可以)两端点连线的斜率之积是定值,定值为
(前提是长轴平行于x轴。若长轴平行于y轴,比如焦点在y轴上的椭圆,可以得到斜率之积为 -a²/b²=1/(e²-1)),可以得出:
在坐标轴内,动点(
)到两定点(
)(
)的斜率乘积等于常数m(-1<m<0)
注意:考虑到斜率不存在时不满足乘积为常数,所以
无法取到,即该定义仅为去掉两个点的椭圆。
令PQ为椭圆的焦点。那么PQ=2c c显然可以得到,对离心率e二分,直到直到满足条件的e,对于一个椭圆来说,椭圆上的点到两焦点的距离2a,所以如果我能找到一个合适的离心率构造出椭圆,最后答案就是2a,但我得满足这个椭圆与圆有交点,不然取不到圆上的点。c是固定值,如果我要改变e,a是未知值,我只能改变b,使离心率改变,所以就有了如下代码。
2.黄金分割三分(不会,只有一份用map的)
为啥可以map呢,-100到100所以可以map
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<cmath>
#include<vector>
#include<stack>
#include<climits>
#include<ctime>
#include<queue>
#define FILEIN freopen("in.txt", "r", stdin)
#define FILEOUT freopen("out.txt", "w", stdout)
#define CLOSEIO ios::sync_with_stdio(false)
#define PI acos(-1)
#define CLR(a) memset(a,0,sizeof(a))
#define MEM(a,x) memset(a,x,sizeof(a))
#define eps 1e-8
#define sf(x) scanf("%d",&x)
#define PB(x) push_back(x)
#define MP(x, y) make_pair(x, y)
#define lowbit(x) x&(-x)
#define fi first
#define se second
#define rep(a,b,c) for(int (a)=(b);(a)<(c);(a)++)
#define drep(a,b,c) for(int (a)=(b);(a)>(c);--(a))
#define dbg(x) cout << #x << "=" << x << endl
#define _ixvii0iv
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;
typedef double db;
const int inf = INT_MAX;
const ll INF = LLONG_MAX;
const ll mod = 1e9 + 7;
ll mul(ll x,ll y){return x*y%mod;}
ll q_mul(ll a, ll b){ ll ans = 0;while(b){if(b & 1){ans=(ans+a)%mod;} b>>=1;a=(a+a) % mod;}return ans;}
ll q_pow(ll x , ll y){ll res=1;while(y){if(y&1) res=q_mul(res,x) ; y>>=1 ; x=q_mul(x,x);} return res;}
ll inv(ll x) { return q_pow(x, mod-2); }
int Read() {
int x = 0, F = 1; char C = getchar();
while (C < '0' || C > '9') { if (C == '-') F = -F; C = getchar(); }
while (C >= '0' && C <= '9') { x = x * 10 - '0' + C, C = getchar(); }
return x * F;
}
struct vis{
int r;
int R;
int len;
bool operator<(const vis &a)const{
if(r!=a.r)
return r<a.r;
else if(R!=a.R)
return R<a.R;
else return len<a.len;
}
bool operator=(const vis &a)const{
return r==a.r&&R==a.R&&len==a.len;
}
};
map<vis,db>mp;
namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(int &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x;
}
inline void read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror)return;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
//getchar->read
inline void read1(int &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(ll &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(double &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (ch=='.'){
double tmp=1;
for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar());
}
if (bo)x=-x;
}
inline void read1(char *s){
char ch=getchar();
for (;blank(ch);ch=getchar());
for (;!blank(ch);ch=getchar())*s++=ch;
*s=0;
}
inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
//scanf->read
inline void read2(int &x){scanf("%d",&x);}
inline void read2(ll &x){
#ifdef _WIN32
scanf("%I64d",&x);
#else
#ifdef __linux
scanf("%lld",&x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void read2(double &x){scanf("%lf",&x);}
inline void read2(char *s){scanf("%s",s);}
inline void read2(char &c){scanf(" %c",&c);}
inline void readln2(char *s){gets(s);}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(ll x){Ostream.print(x);}
inline void println(ll x){Ostream.println(x);}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
//puts->write
char Out[OUT_SIZE],*o=Out;
inline void print1(int x){
static char buf[15];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(int x){print1(x);*o++='\n';}
inline void print1(ll x){
static char buf[25];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(ll x){print1(x);*o++='\n';}
inline void print1(char c){*o++=c;}
inline void println1(char c){*o++=c;*o++='\n';}
inline void print1(char *s){while (*s)*o++=*s++;}
inline void println1(char *s){print1(s);*o++='\n';}
inline void println1(){*o++='\n';}
inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}}
struct puts_write{
~puts_write(){flush1();}
}_puts;
inline void print2(int x){printf("%d",x);}
inline void println2(int x){printf("%d\n",x);}
inline void print2(char x){printf("%c",x);}
inline void println2(char x){printf("%c\n",x);}
inline void print2(ll x){
#ifdef _WIN32
printf("%I64d",x);
#else
#ifdef __linux
printf("%lld",x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void println2(ll x){print2(x);printf("\n");}
inline void println2(){printf("\n");}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
struct point
{
db x,y;
point() {};
point (db _x,db _y)
{
x = _x;
y = _y;
}
inline void input()
{
read(x);
read(y);
}
};
inline int sgn(db x)
{
return x<-eps?-1:x>eps?1:0;
}
typedef point line;
inline db Dot(line a,line b)
{
return a.x*b.x+a.y*b.y;
}
inline line operator +(line a,line b)
{
return line(a.x+b.x,a.y+b.y);
}
inline line operator -(line a,line b)
{
return line(a.x-b.x,a.y-b.y);
}
inline line operator *(line b,db a)
{
return line(b.x*a,b.y*a);
}
inline db len(line a)
{
return sqrt(Dot(a,a));
}
inline db Dis(point a,point b){
return len(b-a);
}
inline line Rotate(line a,db rad)//rad是弧度 负数表示顺时针 正数表示逆时针
{
db cr =cos(rad);
db sr = sin(rad);
return line(a.x*cr-a.y*sr,a.x*sr+a.y*cr);
}
struct circle{
point c;
double r;
circle() {}
circle(point _c,double _r){
c = _c;
r = _r;
}
inline void input(){
c.input();
read(r);
}
};
typedef point line;
int main(){
//FILEIN;
//FILEOUT;
int t = Read();
int ca = 1;
mp.clear();
while(t--){
db R;
point a,b;
read(R);
a.input();
b.input();
int rr = a.x*a.x+a.y*a.y;
int RR = R*R;
int lenn = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
//cout << rr << " " << RR <<" " <<lenn << endl;
if(!(a.x-b.x)&&!(a.y-b.y)){
println(2*(R-len(a)),7);
continue;
}
if(!(a.x+b.x)&&!(a.y+b.y)||!a.x&&!a.y){
println(2*R,7);
continue;
}
vis vs;
vs.R = RR;
vs.r = rr;
vs.len = lenn;
if(mp[vs]){
println(mp[vs],7);
continue;
}
point mab;
mab.x = (a.x+b.x)/2.0;
mab.y = (a.y+b.y)/2.0;
line mm = mab;
db l = 0; db r = PI;
int tm = 0;
db x = R/len(mm);
mm.x*=x;
mm.y*=x;
db diss;
while(r-l>eps){
if(tm>50) break;
db mid1 = (l+r)/2.0;
db mid2 = (r+mid1)/2.0;
line l1 = Rotate(mm,mid1);
line l2 = Rotate(mm,mid2);
db dis1 = Dis(l1,a)+Dis(l1,b);
db dis2 = Dis(l2,a)+Dis(l2,b);
if(sgn(dis2-dis1)>0) r = mid2,diss = dis1;
else l = mid1,diss = dis2;
tm++;
}
mp[vs] = diss;
println(diss,7);
//puts("");
}
}
3.反演
反演:
设在平面内给定一点O和常数k(k不等于零),对于平面内任意一点A,确定A′,使A′在直线OA上一点,并且有向线段OA与OA′满足OA·OA′=k,我们称这种变换是以O为的反演中心,以k为反演幂的反演变换,简称反演。——百度百科
DP+DQ=(DP'+DQ')*k
当 P'Q' 与圆有交点时:
不妨设交点为 O',若 D 不为 O',则 P'D + Q'D > P'Q'(三角形两边之和大于第三边);当且仅当 D 取 O' 时,P'Q + Q'D 取到最小值,即为 P'Q'。
当 P'Q' 与圆无交点时:
PQ 的中垂线与圆的交点一定是使得DP'+DQ'最小的点。OQ'=OP',且DP'=DQ',请仔细想想这个为什么。
MindisTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1182 Accepted Submission(s): 135 Special Judge Problem Description The center coordinate of the circle C is O, the coordinate of O is (0,0) , and the radius is r. P and Q are two points not outside the circle, and PO = QO. You need to find a point D on the circle, which makes PD+QD minimum. Output minimum distance sum. Input The first line of the input gives the number of test cases T; T test cases follow. Each case begins with one line with r : the radius of the circle C. Next two line each line contains two integers x , y denotes the coordinate of P and Q. Limits T≤500000 −100≤x,y≤100 1≤r≤100 Output For each case output one line denotes the answer. The answer will be checked correct if its absolute or relative error doesn't exceed 10−6. Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if |a−b|max(1,b)≤10−6. Sample Input 4 4 4 0 0 4 4 0 3 3 0 4 0 2 2 0 4 0 1 1 0 Sample Output 5.6568543 5.6568543 5.8945030 6.7359174 Source 2017 Multi-University Training Contest - Team 6 Recommend liuyiding | We have carefully selected several similar problems for you: 6107 6106 6105 6104 6103 |
圆心 O 坐标(0, 0), 给定两点 P, Q(不在圆外),满足 PO = QO,
要在圆上找一点 D,使得 PD + QD 取到最小值。
此题会补充三种做法:
1.椭圆
第一定义
平面内与两定点、
的距离的和等于常数
(
)的动点P的轨迹叫做椭圆,即:
第二定义
椭圆平面内到定点(c,0)的距离和到定直线
:
(
不在
上)的距离之比为常数
(即离心率
,0<e<1)的点的轨迹是椭圆。
其中定点
为椭圆的焦点[5] ,定直线
称为椭圆的准线(该定直线的方程是
(焦点在x轴上),或
(焦点在y轴上))。
其他定义
根据椭圆的一条重要性质:椭圆上的点与椭圆长轴(事实上只要是直径都可以)两端点连线的斜率之积是定值,定值为
(前提是长轴平行于x轴。若长轴平行于y轴,比如焦点在y轴上的椭圆,可以得到斜率之积为 -a²/b²=1/(e²-1)),可以得出:
在坐标轴内,动点(
)到两定点(
)(
)的斜率乘积等于常数m(-1<m<0)
注意:考虑到斜率不存在时不满足乘积为常数,所以
无法取到,即该定义仅为去掉两个点的椭圆。
令PQ为椭圆的焦点。那么PQ=2c c显然可以得到,对离心率e二分,直到直到满足条件的e,对于一个椭圆来说,椭圆上的点到两焦点的距离2a,所以如果我能找到一个合适的离心率构造出椭圆,最后答案就是2a,但我得满足这个椭圆与圆有交点,不然取不到圆上的点。c是固定值,如果我要改变e,a是未知值,我只能改变b,使离心率改变,所以就有了如下代码。
//china no.1 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <vector> #include <iostream> #include <string> #include <map> #include <stack> #include <cstring> #include <queue> #include <list> #include <stdio.h> #include <set> #include <algorithm> #include <cstdlib> #include <cmath> #include <iomanip> #include <cctype> #include <sstream> #include <functional> #include <stdlib.h> #include <time.h> #include <bitset> using namespace std; #define pi acos(-1) #define endl '\n' #define srand() srand(time(0)); #define me(x,y) memset(x,y,sizeof(x)); #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++) #define close() ios::sync_with_stdio(0); cin.tie(0); #define FOR(x,n,i) for(int i=x;i<=n;i++) #define FOr(x,n,i) for(int i=x;i<n;i++) #define W while #define sgn(x) ((x) < 0 ? -1 : (x) > 0) #define bug printf("***********\n"); #define db double typedef long long LL; const int INF=0x3f3f3f3f; const LL LINF=0x3f3f3f3f3f3f3f3fLL; const int dx[]={-1,0,1,0,1,-1,-1,1}; const int dy[]={0,1,0,-1,-1,1,-1,1}; const int maxn=2e2+10; const int maxx=1e4+100; const double EPS=1e-7; const int mod=10000007; template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);} template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);} template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));} template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));} inline LL Scan() { int f=1;char C=getchar();LL x=0; while (C<'0'||C>'9'){if (C=='-')f=-f;C=getchar();} while (C>='0'&&C<='9'){x=x*10+C-'0';C=getchar();} x*=f;return x; } //freopen( "in.txt" , "r" , stdin ); //freopen( "data.out" , "w" , stdout ); //cerr << "run time is " << clock() << endl; struct Point { double x, y; Point(double x = 0, double y = 0) : x(x), y(y) { } inline void input() { scanf("%lf%lf",&x,&y); } inline void print() { printf("%.6lf %.6lf\n",x,y); } }; db r; db dis(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int megumi(db e,db c,db B,db r)//e为离心率 { db y=(1-e*e)/(e*e)*B;//椭圆上一点且该点为切点 db a=c/e; db b=sqrt(a*a-c*c); if(y>b) return (b+B>r); double x2=a*a*(1-y*y/(b*b));//x^2 return (x2+(y+B)*(y+B)>r*r)||(B+b>r);//判断条件 } int main() { int t; t=Scan(); while(t--) { scanf("%lf",&r); Point a,b; Point O={0,0}; a.input(),b.input(); double o1=dis(O,a),o2=dis(O,b),o12=dis(a,b); if(fabs(o1-r)<1e-4||fabs(o2-r)<1e-4)//有一个点在圆上 { printf("%.7f\n",o12); continue; } else if(fabs(o12-o1-o2)<1e-4)//同在圆心 { printf("%.7f\n",2*r); continue; } else if(fabs(o12)<1e-4)//P Q重点 { printf("%.7f\n",2*(r-o1)); continue; } db c=o12/2; db B=sqrt(o1*o1-c*c); db l=1e-9,rr=1; //cout<<c<<" "<<B<<endl; int len=35; while(len--) { double m=(l+rr)/2; if(megumi(m,c,B,r)) l=m; else rr=m; } printf("%.7f\n",c/l*2);//2a } }
2.黄金分割三分(不会,只有一份用map的)
为啥可以map呢,-100到100所以可以map
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<cmath>
#include<vector>
#include<stack>
#include<climits>
#include<ctime>
#include<queue>
#define FILEIN freopen("in.txt", "r", stdin)
#define FILEOUT freopen("out.txt", "w", stdout)
#define CLOSEIO ios::sync_with_stdio(false)
#define PI acos(-1)
#define CLR(a) memset(a,0,sizeof(a))
#define MEM(a,x) memset(a,x,sizeof(a))
#define eps 1e-8
#define sf(x) scanf("%d",&x)
#define PB(x) push_back(x)
#define MP(x, y) make_pair(x, y)
#define lowbit(x) x&(-x)
#define fi first
#define se second
#define rep(a,b,c) for(int (a)=(b);(a)<(c);(a)++)
#define drep(a,b,c) for(int (a)=(b);(a)>(c);--(a))
#define dbg(x) cout << #x << "=" << x << endl
#define _ixvii0iv
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;
typedef double db;
const int inf = INT_MAX;
const ll INF = LLONG_MAX;
const ll mod = 1e9 + 7;
ll mul(ll x,ll y){return x*y%mod;}
ll q_mul(ll a, ll b){ ll ans = 0;while(b){if(b & 1){ans=(ans+a)%mod;} b>>=1;a=(a+a) % mod;}return ans;}
ll q_pow(ll x , ll y){ll res=1;while(y){if(y&1) res=q_mul(res,x) ; y>>=1 ; x=q_mul(x,x);} return res;}
ll inv(ll x) { return q_pow(x, mod-2); }
int Read() {
int x = 0, F = 1; char C = getchar();
while (C < '0' || C > '9') { if (C == '-') F = -F; C = getchar(); }
while (C >= '0' && C <= '9') { x = x * 10 - '0' + C, C = getchar(); }
return x * F;
}
struct vis{
int r;
int R;
int len;
bool operator<(const vis &a)const{
if(r!=a.r)
return r<a.r;
else if(R!=a.R)
return R<a.R;
else return len<a.len;
}
bool operator=(const vis &a)const{
return r==a.r&&R==a.R&&len==a.len;
}
};
map<vis,db>mp;
namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(int &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x;
}
inline void read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror)return;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
//getchar->read
inline void read1(int &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(ll &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(double &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (ch=='.'){
double tmp=1;
for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar());
}
if (bo)x=-x;
}
inline void read1(char *s){
char ch=getchar();
for (;blank(ch);ch=getchar());
for (;!blank(ch);ch=getchar())*s++=ch;
*s=0;
}
inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
//scanf->read
inline void read2(int &x){scanf("%d",&x);}
inline void read2(ll &x){
#ifdef _WIN32
scanf("%I64d",&x);
#else
#ifdef __linux
scanf("%lld",&x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void read2(double &x){scanf("%lf",&x);}
inline void read2(char *s){scanf("%s",s);}
inline void read2(char &c){scanf(" %c",&c);}
inline void readln2(char *s){gets(s);}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(ll x){Ostream.print(x);}
inline void println(ll x){Ostream.println(x);}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
//puts->write
char Out[OUT_SIZE],*o=Out;
inline void print1(int x){
static char buf[15];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(int x){print1(x);*o++='\n';}
inline void print1(ll x){
static char buf[25];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(ll x){print1(x);*o++='\n';}
inline void print1(char c){*o++=c;}
inline void println1(char c){*o++=c;*o++='\n';}
inline void print1(char *s){while (*s)*o++=*s++;}
inline void println1(char *s){print1(s);*o++='\n';}
inline void println1(){*o++='\n';}
inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}}
struct puts_write{
~puts_write(){flush1();}
}_puts;
inline void print2(int x){printf("%d",x);}
inline void println2(int x){printf("%d\n",x);}
inline void print2(char x){printf("%c",x);}
inline void println2(char x){printf("%c\n",x);}
inline void print2(ll x){
#ifdef _WIN32
printf("%I64d",x);
#else
#ifdef __linux
printf("%lld",x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void println2(ll x){print2(x);printf("\n");}
inline void println2(){printf("\n");}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
struct point
{
db x,y;
point() {};
point (db _x,db _y)
{
x = _x;
y = _y;
}
inline void input()
{
read(x);
read(y);
}
};
inline int sgn(db x)
{
return x<-eps?-1:x>eps?1:0;
}
typedef point line;
inline db Dot(line a,line b)
{
return a.x*b.x+a.y*b.y;
}
inline line operator +(line a,line b)
{
return line(a.x+b.x,a.y+b.y);
}
inline line operator -(line a,line b)
{
return line(a.x-b.x,a.y-b.y);
}
inline line operator *(line b,db a)
{
return line(b.x*a,b.y*a);
}
inline db len(line a)
{
return sqrt(Dot(a,a));
}
inline db Dis(point a,point b){
return len(b-a);
}
inline line Rotate(line a,db rad)//rad是弧度 负数表示顺时针 正数表示逆时针
{
db cr =cos(rad);
db sr = sin(rad);
return line(a.x*cr-a.y*sr,a.x*sr+a.y*cr);
}
struct circle{
point c;
double r;
circle() {}
circle(point _c,double _r){
c = _c;
r = _r;
}
inline void input(){
c.input();
read(r);
}
};
typedef point line;
int main(){
//FILEIN;
//FILEOUT;
int t = Read();
int ca = 1;
mp.clear();
while(t--){
db R;
point a,b;
read(R);
a.input();
b.input();
int rr = a.x*a.x+a.y*a.y;
int RR = R*R;
int lenn = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
//cout << rr << " " << RR <<" " <<lenn << endl;
if(!(a.x-b.x)&&!(a.y-b.y)){
println(2*(R-len(a)),7);
continue;
}
if(!(a.x+b.x)&&!(a.y+b.y)||!a.x&&!a.y){
println(2*R,7);
continue;
}
vis vs;
vs.R = RR;
vs.r = rr;
vs.len = lenn;
if(mp[vs]){
println(mp[vs],7);
continue;
}
point mab;
mab.x = (a.x+b.x)/2.0;
mab.y = (a.y+b.y)/2.0;
line mm = mab;
db l = 0; db r = PI;
int tm = 0;
db x = R/len(mm);
mm.x*=x;
mm.y*=x;
db diss;
while(r-l>eps){
if(tm>50) break;
db mid1 = (l+r)/2.0;
db mid2 = (r+mid1)/2.0;
line l1 = Rotate(mm,mid1);
line l2 = Rotate(mm,mid2);
db dis1 = Dis(l1,a)+Dis(l1,b);
db dis2 = Dis(l2,a)+Dis(l2,b);
if(sgn(dis2-dis1)>0) r = mid2,diss = dis1;
else l = mid1,diss = dis2;
tm++;
}
mp[vs] = diss;
println(diss,7);
//puts("");
}
}
3.反演
反演:
设在平面内给定一点O和常数k(k不等于零),对于平面内任意一点A,确定A′,使A′在直线OA上一点,并且有向线段OA与OA′满足OA·OA′=k,我们称这种变换是以O为的反演中心,以k为反演幂的反演变换,简称反演。——百度百科
DP+DQ=(DP'+DQ')*k
当 P'Q' 与圆有交点时:
不妨设交点为 O',若 D 不为 O',则 P'D + Q'D > P'Q'(三角形两边之和大于第三边);当且仅当 D 取 O' 时,P'Q + Q'D 取到最小值,即为 P'Q'。
当 P'Q' 与圆无交点时:
PQ 的中垂线与圆的交点一定是使得DP'+DQ'最小的点。OQ'=OP',且DP'=DQ',请仔细想想这个为什么。
//china no.1 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <vector> #include <iostream> #include <string> #include <map> #include <stack> #include <cstring> #include <queue> #include <list> #include <stdio.h> #include <set> #include <algorithm> #include <cstdlib> #include <cmath> #include <iomanip> #include <cctype> #include <sstream> #include <functional> #include <stdlib.h> #include <time.h> #include <bitset> using namespace std; #define pi acos(-1) #define endl '\n' #define srand() srand(time(0)); #define me(x,y) memset(x,y,sizeof(x)); #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++) #define close() ios::sync_with_stdio(0); cin.tie(0); #define FOR(x,n,i) for(int i=x;i<=n;i++) #define FOr(x,n,i) for(int i=x;i<n;i++) #define W while #define sgn(x) ((x) < 0 ? -1 : (x) > 0) #define bug printf("***********\n"); #define db double typedef long long LL; const int INF=0x3f3f3f3f; const LL LINF=0x3f3f3f3f3f3f3f3fLL; const int dx[]={-1,0,1,0,1,-1,-1,1}; const int dy[]={0,1,0,-1,-1,1,-1,1}; const int maxn=2e2+10; const int maxx=1e4+100; const double EPS=1e-7; const int mod=10000007; template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);} template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);} template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));} template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));} inline LL Scan() { int f=1;char C=getchar();LL x=0; while (C<'0'||C>'9'){if (C=='-')f=-f;C=getchar();} while (C>='0'&&C<='9'){x=x*10+C-'0';C=getchar();} x*=f;return x; } //freopen( "in.txt" , "r" , stdin ); //freopen( "data.out" , "w" , stdout ); //cerr << "run time is " << clock() << endl; struct Point { double x, y; Point(double x = 0, double y = 0) : x(x), y(y) { } inline void input() { scanf("%lf%lf",&x,&y); } inline void print() { printf("%.6lf %.6lf\n",x,y); } }; db r; db dis(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } typedef Point Vector; Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); } Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); } Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); } Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); } bool operator < (const Point& a, const Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } int dcmp(double x) { if(fabs(x) < EPS) return 0; else return x < 0 ? -1 : 1; } bool operator == (const Point& a, const Point& b) { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y); } //向量点积 double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } //向量长度 double Length(Vector A) { return sqrt(Dot(A, A)); } //向量叉积 |a||b|sin<a,b> //叉积的结果也是一个向量,是垂直于向量a,b所形成的平面,如果看成三维坐标的话是在 z 轴上,上面结果是它的模。 double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } //点到直线的距离 double DistanceToLine(Point P, Point A, Point B) { Vector v1 = B - A, v2 = P - A; return fabs(Cross(v1, v2) / Length(v1)); //不取绝对值,得到的是有向距离 } int main() { //freopen( "in.txt" , "r" , stdin ); //freopen( "out.txt" , "w" , stdout ); int t; t=Scan(); while(t--) { scanf("%lf",&r); Point a,b; Point O={0,0}; a.input(),b.input(); double o1=dis(O,a),o2=dis(O,b),o12=dis(a,b); if(fabs(o1-r)<1e-4||fabs(o2-r)<1e-4)//有一个点在圆上 { printf("%.10f\n",o12); continue; } else if(fabs(o12-o1-o2)<1e-4)//圆心重合 { printf("%.10f\n",2*r); continue; } else if(fabs(o12)<1e-4)//P Q重点 { printf("%.10f\n",2*(r-o1)); continue; } db k=o1/r; db o11=(db)r*r/o1;//op' db t=o11/o1; Point p1={t*a.x,t*a.y}; Point q1={t*b.x,t*b.y}; db len=DistanceToLine(O,p1,q1); if(dcmp(len-r)<=0)//p1q1与圆相交 { printf("%.10f\n",dis(p1,q1)*k); continue; } else { db h=len-r; db d=dis(p1,q1)/2; db ans=2*sqrt(h*h+d*d); printf("%.10f\n",ans*k); } } }
相关文章推荐
- hdu 6097 Mindis(圆上一点到圆内(距圆心相等的)两点的距离和最短)
- HDU 6097Mindis(利用椭圆二分)
- hdu 6097 Mindis(多校联赛)
- hdu 6097 Mindis(圆上一点到圆内(距圆心相等的)两点的距离和最短)
- HDU_6097 Mindis 【几何】
- hdu 6097 Mindis(圆上一点到圆内(距圆心相等的)两点的距离和最短)
- hdu 6097 Mindis(几何反演)
- HDU 6097 Mindis【几何】
- HDU 6097 Mindis 几何
- 2017 多校训练第六场 HDU 6097 Mindis
- 2017 Multi-University Training Contest - Team 6-HDU 6097:Mindis
- hdu 6097 Mindis(圆上一点到圆内(距圆心相等的)两点的距离和最短)
- hdu 6097 Mindis
- hdu 6097 Mindis
- HDU 6097 Mindis
- HDU 6097 Mindis (计算几何)
- hdu 6097 Mindis(圆上一点到圆内(距圆心相等的)两点的距离和最短)
- HDU 6097 Mindis
- hdu 6097 Mindis
- hdu 6097 Mindis(几何)