1149旅游预算

1149.旅游预算

时限:1000ms 内存限制:10000K  总时限:3000ms

描述

一个旅行社需要估算乘汽车从某城市到另一城市的最小费用,沿路有若干加油站,每个加油站收费不一定相同。旅游预算有如下规则:若油箱的油过半,不停车加油,除非油箱中的油不可支持到下一站;每次加油时都加满;在一个加油站加油时,司机要花费2元买东西吃;司机不必为其他意外情况而准备额外的油;汽车开出时在起点加满油箱;计算精确到分(1元=100分)。编写程序估计实际行驶在某路线所需的最小费用。

输入

第一行为起点到终点的距离(实数)第二行为三个实数,后跟一个整数,每两个数据间用一个空格隔开。其中第一个数为汽车油箱的容量(升),第二个数是每升汽油行驶的公里数,第三个数是在起点加满油箱的费用(精确到分),第四个数是加油站的数量。(〈=50)。接下去的每行包括两个实数,每个数据之间用一个空格分隔,其中第一个数是该加油站离起点的距离,第二个数是该加油站每升汽油的价格(元/升)。加油站按它们与起点的距离升序排列。所有的输入都有一定有解。

输出

共两行,每行都有换行第一行为一个实数和一个整数,实数为旅行的最小费用,以元为单位,精确到分,整数表示途中加油的站的N。第二行是N个整数,表示N个加油的站的编号,按升序排列。数据间用一个空格分隔,最后一个数据后也输出空格,此外没有多余的空格。

输入样例

516.3 15.7 22.1 20.87 3 125.4 1.259 297.9 1.129 345.2 0.999

输出样例

38.09 1

2

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
double pay,length,cap,disper,start;
int mark[60]={0};
double oil[60][2];//oil[i][0]和oil[i][1]分别代表加油站到起点的距离和该加油站的油价
double cost[60];//cost[i]代表在第i个加油站加满油之后后续花费(不包括在第i个加油站加油的费用以及吃饭的费用)//初始化为无限大
int s;
int flag;
int canoil(int i,int j)//从第i个加油站加满油到达第j个加油站之后是否能够在第i个加油站处加油
{
    double a=oil[j][0]-oil[i][0];
    double remain=cap-a/disper;
    if(remain<=cap/2)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
int mustoil(int i,int j)//从第i个加油站加满油到达第j个加油站之后是否必须在第i个加油站处加油
{
    double a=oil[j+1][0]-oil[i][0];
    if(cap-a/disper>=0)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}
void dp()
{
    for(int i=n;i>=0;i--) //在第i个加油站加满了油
    {
        if(i==n)
        {
            cost[i]=0;
        }
        else
        {
            for(int j=i+1;j<=n;j++)//到达第j个加油站处,其中从第i个加油站到第j个加油站中间的加油站不停留
            {
                if(mustoil(i,j))//必须加油
                {
                    pay=(oil[j][0]-oil[i][0])/disper*oil[j][1]+cost[j]+2;//第i个加油站加满油之后的后续花费
                    if(pay<cost[i])
                    {
                        cost[i]=pay;
                        mark[i]=j;
                        break;//因为是必须加油所以循环结束,cost[i]确定
                    }
                }
                else if(canoil(i,j))//可以加油
                {
                    //加油,不加油的选择蕴含在j的其他取值之中
                    pay=(oil[j][0]-oil[i][0])/disper*oil[j][1]+cost[j]+2;
                    if(pay<cost[i])
                    {
                        cost[i]=pay;
                        mark[i]=j;//代表在第i个加油站加满油之后需要在第j个加油站加满油
                    }
                }
            }
        }
    }
}
void tongji()
{
    s=0;
    for(int i=0;i<=n;)
    {
        if(mark[i]!=0)
        {
            s++;
            i=mark[i];
        }
        else
        {
            break;
        }
    }
}
void print()
{
    printf("%.2lf",start+cost[0]);
    cout<<" "<<s<<endl;
    for(int i=0;i<=n;)
    {
        if(mark[i]!=0)
        {
            cout<<mark[i];
            i=mark[i];
            //if(mark[i]!=0)
           // {
                cout<<" ";
           // }
        }
        else
        {
            break;
        }
    }
    cout<<endl;
}
int main()
{
    scanf("%lf%lf%lf%lf%d",&length,&cap,&disper,&start,&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf",&oil[i][0]);
        scanf("%lf",&oil[i][1]);
    }
    for(int i=0;i<=60;i++)
    {
        cost[i]=99999.9;
    }
    oil[n+1][0]=length;
    oil[0][0]=0;
    dp();
    tongji();
    print();
    return 0;
}

参考:https://blog.csdn.net/axiqia/article/details/51188366

猜你喜欢

转载自blog.csdn.net/rain699/article/details/83215758