Codeforce 489E(dp+01分数规划)

来源:互联网 发布:北京市网络挂号平台 编辑:程序博客网 时间:2024/05/17 06:46

链接:点击打开链接

题意:数轴上有n个点,每个点有个距离0点距离xi和价值bi,主人公站在0点,每一步必须落在n个点其中一个上,走到点n后可以计算旅行的价值,对于所有走过的点i,val=∑(sqrt(abs(x[i]-x[i-1]-len))/b[i]),当val最小时,输出走过的路径

代码:

#include <math.h>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int INF=0x3f3f3f3f;double dp[1005];int n,len;int x[1005],y[1005],pre[1005];int judge(double s){    int i,j;    for(i=1;i<=n;i++){        pre[i]=0;        dp[i]=INF*1.0;    }    dp[0]=0;    for(i=1;i<=n;i++){        for(j=0;j<i;j++){            if(dp[i]>dp[j]+sqrt(fabs(x[i]-x[j]-len)*1.0)-y[i]*s){                dp[i]=dp[j]+sqrt(fabs(x[i]-x[j]-len)*1.0)-y[i]*s;                pre[i]=j;            }                                   //ans=∑(sqrt(abs(x[i]-x[i-1]-len))/∑(b[i])        }                                       //所以构造出函数    }                                           //F(ans)=∑(sqrt(abs(x[i]-x[i-1]-len))-∑(b[i])*ans    if(dp[n]<=0)                                //很明显是关于ans单调的,因此对ans进行二分,求出F(ans)==0的    return 1;                                   //最小ans,儿二分的判断条件恰好可以用dp进行判断    return 0;}void print(int s){    if(s==0)    return;    print(pre[s]);    if(s==n)    printf("%d\n",s);    else    printf("%d ",s);}int main(){                                     //因为dp不能维护两个值,而且也不允许在开一维    int i,j;                                    //所以不能直接dp    double l,r,ans,mid;    while(scanf("%d%d",&n,&len)!=EOF){        for(i=1;i<=n;i++)        scanf("%d%d",&x[i],&y[i]);        l=0,r=INF*1.0;        for(i=1;i<=100;i++){            mid=(l+r)*0.5;            if(judge(mid))            r=mid;            else            l=mid;        }        judge(r);                               //输出路径        print(n);    }    return 0;}

0 0