【BZOJ5471】[FJOI2018]郵遞員問題(動態規劃)
阿新 • • 發佈:2019-02-28
出發 強制 [1] std calc() .com etc 問題 路徑
設\(f[j][1]\)表示第\(1\)行\([j,n_1]\)已經走完,第\(0\)行\([i+1,n_0]\)已經走完,然後達到終點的最短路。
把\(i\)按照從前往後或者從後往前的順序枚舉,到達起點就直接更新答案。
因為從起點出發可以向兩個方向走,所以前後都要做一遍\(dp\)。
轉移的話就是一堆討論。
【BZOJ5471】[FJOI2018]郵遞員問題(動態規劃)
題面
BZOJ
洛谷
給定平面上若幹個點,保證這些點在兩條平行線上,給定起點終點,求從起點出發,遍歷所有點後到達終點的最短路徑長度。
題解
不會做,於是點開LOJ,點開除了\(std\)之外唯一過的人的代碼,照著打了一遍QwQ......
然後再對著代碼YY一遍就有了這篇東西。。。。。。
強制令起點的位置是第\(0\)行(方便而已)。
在第\(0\)行枚舉一個\(i\),在第一行枚舉一個\(j\)。
設\(f[j][0]\)表示第\(1\)行\([j+1,n_1]\)這些點已經走完,第\(0\)行\([i,n_0]\)已經走完,然後到達終點的最短路。
把\(i\)按照從前往後或者從後往前的順序枚舉,到達起點就直接更新答案。
因為從起點出發可以向兩個方向走,所以前後都要做一遍\(dp\)。
轉移的話就是一堆討論。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define MAX 10100 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int n[2],ty[2],pos[2]; double h,tx[2],x[2][MAX],f[MAX][2]; double Dis(int i,int j) { double d=fabs(x[0][i]-x[1][j]); return sqrt(d*d+h*h); } double ToEnd(int i,int j) { double d=fabs(x[i][j]-tx[1]); return i==ty[1]?d:sqrt(h*h+d*d); } double Calc() { double ret=1e18; sort(&x[0][1],&x[0][n[0]+1]); sort(&x[1][1],&x[1][n[1]+1]); for(int i=n[0];i;--i) { if(i==n[0]) for(int j=n[1];j;--j) { f[j][0]=j==n[1]?ToEnd(0,n[0]):min(f[j+1][1]+Dis(n[0],j+1),Dis(n[0],n[1])+x[1][n[1]]-x[1][j+1]+ToEnd(1,j+1)); f[j][1]=j==n[1]?ToEnd(1,n[1]):f[j+1][1]+x[1][j+1]-x[1][j]; } else for(int j=n[1];j;--j) if(j==n[1]) { f[j][1]=min(f[j][0]+Dis(i+1,j),Dis(n[0],n[1])+x[0][n[0]]-x[0][i+1]+ToEnd(0,i+1)); f[j][0]+=x[0][i+1]-x[0][i]; } else { f[j][1]=min(f[j][0]+Dis(i+1,j),f[j+1][1]+x[1][j+1]-x[1][j]); f[j][0]=min(f[j][0]+x[0][i+1]-x[0][i],f[j+1][1]+Dis(i,j+1)); } ret=min(ret,x[0][i]-x[0][1]+tx[0]-x[0][1]+Dis(i,1)+f[1][1]); ret=min(ret,fabs(x[0][i]-tx[0])+x[0][i]-x[0][1]+Dis(1,1)+f[1][1]); if(x[0][i]<=tx[0]) { ret=min(ret,tx[0]-x[0][1]+Dis(1,1)+f[1][1]); break; } } return ret; } int main() { scanf("%d%d%d%d%d%d%lf",&n[0],&n[1],&ty[0],&pos[0],&ty[1],&pos[1],&h); int r=0;if(ty[0])r=1,swap(n[0],n[1]),ty[0]^=1,ty[1]^=1; for(int t=0;t<=1;++t) for(int i=1;i<=n[t^r];++i) scanf("%lf",&x[t^r][i]); tx[0]=x[ty[0]][pos[0]]; tx[1]=x[ty[1]][pos[1]]; double ans=Calc(); for(int t=0;t<=1;++t) for(int i=1;i<=n[t];++i) x[t][i]=20000-x[t][i]; tx[0]=20000-tx[0];tx[1]=20000-tx[1]; ans=min(ans,Calc()); printf("%.2lf\n",ans); return 0; }
【BZOJ5471】[FJOI2018]郵遞員問題(動態規劃)