SGU 331 Traffic Jam(离散化+DP)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=331

题意:给出n个跑道,每个跑道的参数有三个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\n",x);}

void PR(i64 x) {printf("%I64d\n",x);}

void PR(u32 x) {printf("%u\n",x);}

void PR(double x) {printf("%.6lf\n",x);}

void PR(char x) {printf("%c\n",x);}

void PR(char *x) {printf("%s\n",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\n",Min);

    printf("%d\n",SZ(ans));

    for(i=SZ(ans)-1;i>=0;i--)

    {

        printf("%d %.15f\n",ans[i].first,ans[i].second);

    }

    return 0;

}

  

你可能感兴趣的:(dp)