洛谷NOIP刷题-P1016 旅行家的预算

2018信息学奥赛NOIP全套视频

题目描述
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1D1、汽车油箱的容量CC(以升为单位)、每升汽油能行驶的距离D2D2、出发点每升汽油价格PP和沿途油站数NN(NN可以为零),油站ii离出发点的距离DiDi、每升汽油价格PiPi(i=1,2,…,Ni=1,2,…,N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

输入输出格式
输入格式:
第一行,D1D1,CC,D2D2,PP,NN。

接下来有NN行。

第i+1i+1行,两个数字,油站i离出发点的距离DiDi和每升汽油价格PiPi。

输出格式:
所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

输入输出样例
输入样例#1:
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
输出样例#1:
26.95
说明
N \le 6N≤6,其余数字 \le 500≤500

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<ctime>
#define INF 0x3f3f3f3f
typedef long long LL;
using namespace std;
double dp[10][50005],len,c,v,w[10],s[10],ans,cs[10],m[10];
int n,fl,l=1,r;
int main()
{
    scanf("%lf%lf%lf%lf%d",&len,&c,&v,&w[0],&n);
    for(int i=1;i<=n;i++) {
        scanf("%lf%lf",&s[i],&w[i]);
    }
    s[n+1]=len;
    for(int i=0;i<=n;i++) {
        double now=(s[i+1]-s[i])/v;
        if(now>c) {fl=1;break;}
        if(l>r||w[i]<=cs[l]) {
            l=1;r=0;
            ans+=w[i]*now;
            
        }
        else {
            double tmp=0;
            while(w[i]>cs[l]&&tmp<now) {
                if(now-tmp<m[l]) {
                    ans+=cs[l]*(now-tmp);
                    m[l]-=(now-tmp);
                    tmp=now;
                }
                else {
                    ans+=cs[l]*m[l];
                    tmp+=m[l];
                    l++;
                }
            }
            if(tmp<now) {
                ans+=(now-tmp)*w[i];
            }
        }
        if(c-now>0) {
            cs[++r]=w[i];
            m[r]=c-now;
            for(int i=l;i<r;i++) m[r]-=m[i];
        }
    }
    if(fl) cout<<"No Solution"<<endl;
    else printf("%.2lf\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianli315/article/details/87930002