P1995
总体来说,有一定难度,听我细细道来……
一看,这题不是要用DP吗?然后懵圈十分钟,继续懵圈……
十分不可做,但是我想到了贪心!!!!!(告诉我信竞的重要性!!!!
-
我们例举样例,然后询问教练可知
-
时间复杂度为
O(n^2) -
列出状态转移方程(教练给的
F[i]=\min(F[i],F[j]+len(i,j))
此题结束! 最后附上AC代码(也是教练手写的!
#include <bits/stdc++.h>
#define ERO (1e7)
#define ESP (1e-12)
#define XX(x) ((x)*(x))
#define fabs(x) ((x)>0?(x):-(x))
#define ET0(x) (fabs(x)<=ESP)
using namespace std;
struct Point{
double x,y;
Point operator + (Point p)
{
p.x+=x;p.y+=y;
return p;
}
Point operator - (Point p)
{
p.x=-p.x+x;p.y=-p.y+y;
return p;
}
Point operator * (double lambda)
{return {x*lambda,y*lambda};}
double operator * (Point p)
{return x*p.x+y*p.y;}
double operator % (Point p)
{return x*p.y-y*p.x;}
bool operator == (Point p)
{return ET0(x-p.x)&&ET0(y-p.y);}
};
struct Line{
Point p1,p2;
};
double Dist(Point p1,Point p2)
{return sqrt(XX(p1.x-p2.x)+XX(p1.y-p2.y));}
Point Intersection(Line l1,Line l2)
{
Point re;
double c1x=l1.p2.x-l1.p1.x,c2x=l2.p2.x-l2.p1.x,c1y=l1.p2.y-l1.p1.y,c2y=l2.p2.y-l2.p1.y;
re.x=(c1y*c2x*l1.p1.x-c1x*c2y*l2.p1.x+c1x*c2x*(l2.p1.y-l1.p1.y))/(c1y*c2x-c1x*c2y);
re.y=(c1x*c2y*l1.p1.y-c1y*c2x*l2.p1.y+c1y*c2y*(l2.p1.x-l1.p1.x))/(c1x*c2y-c1y*c2x);
return re;
}
Line Door[2018];
Point path[2018],Rect[2018][2];
double sx,sy,tx,ty,speed,lastmindis=0,mindis=1e9;
int n;
int main()
{
srand(time(NULL));
cin.sync_with_stdio(false);
cin.tie(0);
cin>>n>>Rect[1][0].x>>Rect[1][0].y>>Rect[1][1].x>>Rect[1][1].y;
for (int i=2;i<=n;++i)
cin>>Rect[i][0].x>>Rect[i][0].y>>Rect[i][1].x>>Rect[i][1].y,
Door[i-1].p1={Rect[i][0].x,max(Rect[i-1][0].y,Rect[i][0].y)},
Door[i-1].p2={Rect[i][0].x,min(Rect[i-1][1].y,Rect[i][1].y)};
cin>>sx>>sy>>tx>>ty>>speed;
if (sx>tx) swap(sx,tx),swap(sy,ty);
int Pos1=1,Pos2=n-1;
while (Pos1<=n-1&&Door[Pos1].p1.x<=sx)
++Pos1;
if (Door[Pos1-1].p1.x==sx&&(Door[Pos1-1].p1.y>sy||Door[Pos1-1].p2.y<sy)
&&Rect[Pos1-2][0].y<=sy&&sy<=Rect[Pos1-2][1].y) --Pos1;//最后的错误所在,少了这个特判,没有考虑好起止的情况,结果调了一天
while (Pos2>=1&&Door[Pos2].p1.x>=tx)
--Pos2;
if (Door[Pos2+1].p1.x==tx&&(Door[Pos2+1].p1.y>ty||Door[Pos2+1].p2.y<ty)
&&Rect[Pos2+2][0].y<=ty&&ty<=Rect[Pos2+2][1].y) ++Pos2;
path[Pos1-1]={sx,sy};
path[Pos2+1]={tx,ty};
for (int i=Pos1;i<=Pos2;++i)
path[i]=(Door[i].p1+Door[i].p2)*0.5;
while (lastmindis!=mindis)
{
lastmindis=mindis;
mindis=0;
for (int i=Pos1;i<=Pos2;++i)
{
Line l;l.p1=path[i-1];l.p2=path[i+1];
Point p=Intersection(l,Door[i]);
if (p.y>=Door[i].p1.y&&p.y<=Door[i].p2.y) path[i]=p;
else
if ((path[i]-path[i-1])%(path[i+1]-path[i])>0)//向下凸
path[i]=Door[i].p2;
else path[i]=Door[i].p1;
mindis+=Dist(path[i],path[i-1]);
}
mindis+=Dist(path[Pos2],path[Pos2+1]);
}
printf("%.8lf\n",mindis/speed);
return 0;
}