牛客國慶集訓派對Day1 New Game!+計算幾何
阿新 • • 發佈:2018-11-17
題目連結:https://www.nowcoder.com/acm/contest/201/L
題目大意:給你n個圓和兩條直線,在圓上,和圓內和直線上行走不消耗體力。
在其他位置上由S點走到T點消耗的體力為S和T的歐幾里得距離。Hifumi Takimoto想從 L1 出發,走到 L2 。請計算最少需要多少體力。
思路:因為圓與直線的位置可以任意。從L1到L2,我們計算從c大的直線的到c小的直線距離就好了,如圖L1->L2。
其實思路就是dp最短路。我們先按照圓與L1的距離排序。(排序依據不只是距離,因為可能在直線外)
int px(O pa, O pb) { if(a*pa.x+b*pa.y+c1<0&&a*pb.x+b*pb.y+c1<0)//都在L1左邊,按照距離L1的距離從大到小 return pa.s<pb.s; else if(a*pa.x+b*pa.y+c1>0&&a*pb.x+b*pb.y+c1>0)//都在L1右邊,按照距離L1的距離從小到大 return pa.s>pb.s; else return a*pa.x+b*pa.y+c1<a*pb.x+b*pb.y+c1?0:1;//一左一右,左在右前 }
所以遞推公式(dp[i].s為初始到L1的距離)
dp[i].s=min(dp[j].s,d[i].s), j<i。
因為n<=1000;直接兩種迴圈暴力。
先初始化s[i].s=d。
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
//d(ij)如圖的黃色虛線距離。
dp[j].s=(dp[i].s, d(ij));
}
}
這樣求出所有圓到L1的距離,在加上該圓的到L2的距離。
再求dp[i].s的最小距離就行了。
思考:這題當時寫了兩個小時,因為犯了不少錯誤。最後AC的瞬間,高興跳起來的歡呼。這可能就是ACM的魅力吧!。
#include<bits/stdc++.h> using namespace std; struct O { double x; double y; double r; double s; }; O w[1005]; long long n, a, b, c1, c2; int px(O pa, O pb) { if(a*pa.x+b*pa.y+c1<0&&a*pb.x+b*pb.y+c1<0) return pa.s<pb.s; else if(a*pa.x+b*pa.y+c1>0&&a*pb.x+b*pb.y+c1>0) return pa.s>pb.s; else return a*pa.x+b*pa.y+c1<a*pb.x+b*pb.y+c1?0:1; } int px1(O pa, O pb) { return pa.s<pb.s; } int main() { scanf("%lld%lld%lld%lld%lld",&n, &a, &b, &c1, &c2); for(int i=0;i<n;i++) { scanf("%lf%lf%lf",&w[i].x, &w[i].y, &w[i].r); }; if(c1>c2) swap(c1, c2); for(int i=0;i<n;i++)//初始化 { double fz=fabs(a*w[i].x+b*w[i].y+c1); double fm=sqrt(a*a+b*b); double f1=fz/fm; if(f1<=w[i].r) w[i].s=0; else w[i].s=f1-w[i].r; } sort(w,w+n, px);//圓的排序 for(int i=0;i<n;i++)//dp遞推 { for(int j=i+1;j<n;j++) { double s1=sqrt((w[i].x-w[j].x)*(w[i].x-w[j].x)+(w[i].y-w[j].y)*(w[i].y-w[j].y)); double s2=w[i].r+w[j].r; if(s1>s2) w[j].s=min(w[i].s+s1-s2, w[j].s); else w[j].s=min(w[i].s, w[j].s); } } for(int i=0;i<n;i++)//加上到L2的距離 { double fz=fabs(a*w[i].x+b*w[i].y+c2); double fm=sqrt(a*a+b*b); double f1=fz/fm; if(f1<=w[i].r) w[i].s+=0; else w[i].s+=f1-w[i].r; } sort(w,w+n, px1);//按s從小到大排序 printf("%.6f\n",w[0].s); return 0; }