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<float.h>
#include<stdio.h>
#define DBL_MAX 1.7976931348623158e+308
using namespace std;
/************************/
int n;
double length;
double cap,mile,cost;
double dist[51],prize[51];
/************************/
int addoil[51];
double memo[51];//备忘录
double maxdist; //the max dist after pour in oil
/***********************/
double dp(int i);
double dp(int i)
{
if(i==n+1)
return cost;
else if(memo[i]!=DBL_MAX)
return memo[i];
else
{
double fuel_j; //fuel from i to j
double fuel_rest; //the rest fuel after from i to j
double cost_j; //from i to j and add oil in j
double cost_j_n; //total cost from i to j to end
int addoil_j=-1; //the station need to add oil
for(int j=i+1;j<=n+1 && (dist[j]-dist[i])<=maxdist;j++)
{
fuel_j=(dist[j]-dist[i])/mile;
fuel_rest=cap-fuel_j;
if(fuel_rest>cap/2 && fuel_rest*mile>=(dist[j+1]-dist[j]))
continue;
if(j==n+1)
cost_j=0;
else
{
cost_j=2;
cost_j+=fuel_j*prize[j]; //消耗的油*油价=加满油
}
cost_j_n=cost_j+dp(j);
if(memo[i]>cost_j_n)
{
memo[i]=cost_j_n;
addoil_j=j;
}
}
if(addoil_j!=-1)
addoil[addoil_j]=1;
return memo[i];
}
}
int main()
{
int count=0;
cin>>length;//input
cin>>cap>>mile>>cost>>n;
int i=1;
while(i<=n)
{
cin>>dist[i]>>prize[i];
i++;
}
for(int i=0;i<=n;i++)
{
memo[i]=DBL_MAX;
}
dist[0]=0;
dist[n+1]=length;
maxdist=cap*mile;//
double mincost=dp(0);
printf("%.2lf ",mincost);//first line
for(int i=1;i<=n;i++)
{
if(addoil[i])
count++;
}
cout<<count<<endl;//second line
for(int i=1;i<=n;i++)
{
if(addoil[i])
cout<<i<<" ";
}
cout<<endl;//
return 0;
}