「ICPC World Finals 2019」美麗的橋樑
阿新 • • 發佈:2020-09-18
「ICPC World Finals 2019」美麗的橋樑
可以得到一個Naive的暴力方法來判斷在\((L,R)\)上修橋是否合法:
顯然的性質: 如果有相交,則一定存在一個關鍵點相交
設得到的圓半徑為\(r=\frac{x_R-x_L}{2}\),圓心為\((x,y)=(\frac{x_L+x_R}{2},h-r)\)
列舉每個\(i\in [L,R]\)判斷是否點\(x_i,y_i\)是否相交,如果相交,只需要滿足
\(y_i>y\),且 其與圓心距離\(>r\)
\[\ \]
考慮優化判斷,將生成的拱形分為左右兩部分,分別考慮即可
推論: 對於每個\(L\),其左半邊不相交的半徑為描述為一個範圍\([0,A_L]\)
同理的,對於每個\(R\)也是如此,能求得一個範圍\([0,B_R]\)
考慮對於每個\(L\),列舉每個\(i>L\) 來求出\(A_L\)
設半徑為\(r\),列出圓心與點\(x_i,y_i\)距離的表示式,必須滿足距離\(\leq r\),就能得到一個二次方程
二次方程的解集為\(x_1,x_2\),但是實際上\([0,x_1]\)這一段不滿足\(y_i>y\),因此也是合法的
即將每次求得的\([0,x_2]\)區間取交集即可
複雜度為\(O(n^2)\)
同理求得每個\(B_R\)
考慮樸素的dp,令\(dp_i\)表示解決了\([1,i]\)字首的最小代價
列舉\(j\),\(O(1)\)
tips: 題目的代價計算方法可能沒講清楚。。。
複雜度為\(O(n^2)\)
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) typedef double db; typedef long long ll; #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i) template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); } template <class T> inline void cmax(T &a,const T &b){ ((a<b)&&(a=b)); } char IO; template <class T=int> T rd(){ T s=0; int f=0; while(!isdigit(IO=getchar())) if(IO=='-') f=1; do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return f?-s:s; } const int N=1e4+10; const db eps=1e-9; const ll INF=4e18; int n,h,a,b; int X[N],Y[N]; db L[N],R[N]; db Sqr(db x){ return x*x; } ll dp[N]; int main(){ n=rd(),h=rd(),a=rd(),b=rd(); rep(i,1,n) X[i]=rd(),Y[i]=rd(); rep(i,1,n) { L[i]=min((db)(X[n]-X[i])/2,(db)(h-Y[i])); rep(j,i+1,n) { if(X[j]-X[i]>L[i]+eps) break; db a=1,b=2*(X[i]-X[j]+Y[j]-h),c=Sqr(X[i]-X[j])+Sqr(Y[j]-h); db d=sqrt(b*b-4*a*c); db r=(-b+d)/(2*a); cmin(L[i],r); } L[i]*=2; } rep(i,1,n) { R[i]=min((db)(X[i]-X[1])/2,(db)(h-Y[i])); drep(j,i-1,1) { if(X[i]-X[j]>R[i]+eps) break; db a=1,b=2*(X[j]-X[i]+Y[j]-h),c=Sqr(X[j]-X[i])+Sqr(Y[j]-h); db d=sqrt(b*b-4*a*c); db r=(-b+d)/(2*a); cmin(R[i],r); } R[i]*=2; } dp[1]=1ll*a*(h-Y[1]); rep(i,2,n) { dp[i]=INF; drep(j,i-1,1) { if(X[i]-X[j]>R[i]+eps) break; if(X[i]-X[j]>L[j]+eps) continue; cmin(dp[i],dp[j]+1ll*a*(h-Y[i])+1ll*(X[i]-X[j])*(X[i]-X[j])*b); } } if(dp[n]<INF) printf("%lld\n",dp[n]); else puts("impossible"); }