SGU 331 Traffic Jam(離散化+DP)
6476 ワード
タイトルリンク:http://acm.sgu.ru/problem.php?contest=0&problem=331
題意:n個の滑走路が与えられ、各滑走路のパラメータは3個のai,bi,detiがあり、t時点でi番目の滑走路での速度がbi+ai*sin(t+deti)であることを示す.iからjに移行する費用はc*abs(i-j)である.総距離d.走り終わるdの最小時間を求めます.最初は1番レーンでした.
構想:滑走路転換時刻t:bi+ai*(t+deti)=bj+aj*sin(t+detj+c*abs(i-j))すべてのtを求め、その番号とする.f[i][j]は、時刻jがi滑走路を走る最大距離を示す.
題意:n個の滑走路が与えられ、各滑走路のパラメータは3個のai,bi,detiがあり、t時点でi番目の滑走路での速度がbi+ai*sin(t+deti)であることを示す.iからjに移行する費用はc*abs(i-j)である.総距離d.走り終わるdの最小時間を求めます.最初は1番レーンでした.
構想:滑走路転換時刻t:bi+ai*(t+deti)=bj+aj*sin(t+detj+c*abs(i-j))すべてのtを求め、その番号とする.f[i][j]は、時刻jがi滑走路を走る最大距離を示す.
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-10
#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define DOW0(i,x) for(i=x;i>=0;i--)
#define DOW1(i,x) for(i=x;i>=1;i--)
#define DOW(i,a,b) for(i=a;i>=b;i--)
using namespace std;
void RD(int &x){scanf("%d",&x);}
void RD(i64 &x){scanf("%I64d",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}
void PR(int x) {printf("%d
",x);}
void PR(i64 x) {printf("%I64d
",x);}
void PR(u32 x) {printf("%u
",x);}
void PR(double x) {printf("%.6lf
",x);}
void PR(char x) {printf("%c
",x);}
void PR(char *x) {printf("%s
",x);}
void PR(string x) {cout<<x<<endl;}
const int N=10;
const int M=50005;
vector<pair<int,double> > ans;
vector<double> T;
double f[N][M];
int path[N][M];
double det[N],c,d,maxtime;
int a[N],b[N],n;
void getctime(int i,int j)
{
int k;
double A,B,C,D,x,y,z,t,t1,t2;
vector<double> V;
x=a[i]*cos(det[i])-a[j]*cos(det[j]+c*abs(i-j));
y=a[i]*sin(det[i])-a[j]*sin(det[j]+c*abs(i-j));
z=b[i]-b[j];
A=z*z-x*x;
B=-2.0*x*y;
C=z*z-y*y;
if(fabs(A)+fabs(B)>EPS)
{
if(fabs(A)<EPS)
{
t=atan(-C/B);
if(t<-EPS) t=t+PI;
while(t<maxtime) V.pb(t),t+=PI;
}
else
{
D=B*B-4.0*A*C;
if(D>-EPS)
{
D=sqrt(fabs(D));
t1=0.5*(-B-D)/A;
t2=0.5*(-B+D)/A;
t=atan(t1);
if(t<-EPS) t+=PI;
while(t<maxtime) V.pb(t),t+=PI;
t=atan(t2);
if(t<-EPS) t+=PI;
while(t<maxtime) V.pb(t),t+=PI;
}
}
}
for(k=0;k<SZ(V);k++)
{
if(fabs(z+x*sin(V[k])+y*cos(V[k]))<1e-5)
{
T.pb(V[k]);
T.pb(V[k]+c*abs(i-j));
}
}
}
double getdist(double t,double x,int i)
{
return b[i]*x+a[i]*(cos(t+det[i])-cos(t+det[i]+x));
}
double gettime(double t,double dis,int i)
{
double low=0.0,high=2*d,mid;
while(low-high<-EPS)
{
mid=(low+high)*0.5;
if(getdist(t,mid,i)<dis) low=mid;
else high=mid;
}
return mid;
}
int getnextpos(int low,int high,double value)
{
int mid;
while(low<=high)
{
mid=(low+high)>>1;
if(T[mid]<value-EPS) low=mid+1;
else if(T[mid]>value+EPS) high=mid-1;
else return mid;
}
return -1;
}
void input()
{
int i,j;
scanf("%d%lf%lf",&n,&d,&c);
maxtime=0;
FOR1(i,n)
{
scanf("%d%d%lf",&a[i],&b[i],&det[i]);
T.pb(c*(i-1));
maxtime=max(maxtime,gettime(0,d,i));
}
FOR1(i,n) FOR1(j,n) if(i!=j) getctime(i,j);
sort(T.begin(),T.end());
T.erase(unique(T.begin(),T.end()),T.end());
}
int main()
{
input();
int i,j,k,x,y,ansI,ansJ;
double temp,Min=1e20;
FOR0(i,N) FOR0(j,M) f[i][j]=-2;
f[1][0]=0.0;
FOR0(j,SZ(T)) FOR1(i,n) if(f[i][j]>-EPS&&f[i][j]<=d)
{
temp=gettime(T[j],d-f[i][j],i);
if(Min>T[j]+temp) Min=T[j]+temp,ansI=i,ansJ=j;
FOR1(x,n) if(x!=i)
{
y=getnextpos(j+1,SZ(T)-1,T[j]+c*abs(x-i));
if(y!=-1&&f[x][y]<f[i][j])
{
f[x][y]=f[i][j];
path[x][y]=i;
}
}
k=j+1;
temp=getdist(T[j],T[k]-T[j],i);
if(f[i][k]<f[i][j]+temp)
{
f[i][k]=f[i][j]+temp;
path[i][k]=i;
}
}
while(ansJ!=0)
{
if(path[ansI][ansJ]==ansI)
{
ansJ--;
continue;
}
temp=T[ansJ]-c*abs(ansI-path[ansI][ansJ]);
ans.pb(MP(ansI,temp));
ansI=path[ansI][ansJ];
while(T[ansJ]>temp) ansJ--;
}
printf("%.15f
",Min);
printf("%d
",SZ(ans));
for(i=SZ(ans)-1;i>=0;i--)
{
printf("%d %.15f
",ans[i].first,ans[i].second);
}
return 0;
}