旅游预算
2016-04-19 11:01
204 查看
描述
一个旅行社需要估算乘汽车从某城市到另一城市的最小费用,沿路有若干加油站,每个加油站收费不一定相同。旅游预算有如下规则: 若油箱的油过半,不停车加油,除非油箱中的油不可支持到下一站;每次加油时都加满;在一个加油站加油时,司机要花费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
动态规划
oil[i][0]:加油站i到起点的距离
oil[i][1]:加油站i的油价
cost[i]:加油站i处加满油到达终点的最小花费
那么类似于矩阵连乘积和石子合并问题:
在满足题意的情况下,i处加满油后,直到j处才再次加油(i到j中间的油站不加油)
cost[i] = min(cost[i],(oil[j][0]-oil[i][0])/kilometer*oil[j][1]+cost[j]+2);
一个旅行社需要估算乘汽车从某城市到另一城市的最小费用,沿路有若干加油站,每个加油站收费不一定相同。旅游预算有如下规则: 若油箱的油过半,不停车加油,除非油箱中的油不可支持到下一站;每次加油时都加满;在一个加油站加油时,司机要花费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
动态规划
oil[i][0]:加油站i到起点的距离
oil[i][1]:加油站i的油价
cost[i]:加油站i处加满油到达终点的最小花费
那么类似于矩阵连乘积和石子合并问题:
在满足题意的情况下,i处加满油后,直到j处才再次加油(i到j中间的油站不加油)
cost[i] = min(cost[i],(oil[j][0]-oil[i][0])/kilometer*oil[j][1]+cost[j]+2);
#include <iostream> #include <cstdio> using namespace std; int n; double pay; double length; double oil[52][2]; double cost[52]; double capacity, kilometer, start; int mark[52]; int sum; //i处加满到达j时能否加油 bool Canoil(int i, int j) { double sum = oil[j][0]-oil[i][0]; //加油站i和j的距离 double remain = capacity-sum/kilometer; //油箱从i到j剩余的余量 if(remain <= capacity/2) return true; return false; } //i处加满油到达j时是否必须加油 //oil[j+1][0]-oil[i][0] //j处不加油需要保证能到达j+1 bool Mustoil(int i , int j) { double sum = oil[j+1][0]-oil[i][0]; if(capacity*kilometer < sum) //油箱不足以支撑从i到j return true; return false; } void Search() { for(int i = n; i >= 0; i --) //i处加满油 { int flag = 0; if(i == n) //题目必有解,则可到达终点 cost[i] = 0; else { for(int j = i+1; j <= n; j++) //i处加满油后,直到j处才再次加油(i到j中间的油站不加油) { if(Mustoil(i, j)) //i到j油量不够,必须加油 { //i处油箱满,j处再次加满油,i到j的耗油量(oil[j][0]-oil[i][0])/kilometer即为j处需要加的油量 pay = (oil[j][0]-oil[i][0])/kilometer*oil[j][1]+cost[j]+2; if(flag == 0 || pay < cost[i]) { cost[i] = pay; mark[i] = j; j = n+1; //j处必须加满油,结束循环,因为j处加满油的最小花费已经计算过了 } } else if(Canoil(i, j)) //油量小于一半,可以加油 { //可以加油,那么在j处要么加油,要么不加油 //尝试加油,不加油的状态隐含在j的其他值中 pay = (oil[j][0]-oil[i][0])/kilometer*oil[j][1]+cost[j]+2; if(flag == 0 || pay < cost[i]) { cost[i] = pay; flag = 1; mark[i] = j; } } } } } } //统计最小花费下加油站的数目 void res() { for(int i=0; i<=n;) { if(mark[i]!=0) { sum++; i=mark[i]; } else break; } } //按照格式输出 void Print() { printf("%.2lf",cost[0]+start); cout<<" "<<sum<<endl; for(int i=0; i<=n;) { if(mark[i]!=0) { cout<<mark[i]; i=mark[i]; if(i<=n) { cout<<" "; } } else break; } cout<<endl; } int main() { cin >> length; //起点到终点的距离 cin >> capacity; //油箱的容量 cin >> kilometer; //每公里的耗油量 cin >> start; //起点的加油费 cin >> n; //加油站的数目 for(int i = 1; i <= n; i++) { cin >> oil[i][0] >> oil[i][1]; //oil[i][0]:加油站i到起点的距离 //oil[i][1]:加油站i的油价 } oil[n+1][0] = length; //终点,判断是否必须加油需要用到 oil[0][0]=0; //起点 Search(); //求解 res(); //统计最小花费下加油站的数目 Print(); //输出 }
相关文章推荐
- Oracle 时间段查询
- NSURLSessionConfiguration
- 进程间通讯方式总结
- UVA_465_Overflow
- python文件命名陷阱
- App跳转到与手机版QQ公众服务号聊天界面
- C++11新语法--01 Lambda表达式
- 需求评审流程规范图
- [Linux] Netstat 执行过慢,占CPU100%,原因查找
- Struts2进行url重写
- HDU 5559 Frog and String 构造
- Syslog-ng+Rsyslog收集日志:rsyslog配置(二)
- 关于ListView数据减少时,未能刷新
- codevs1024一塔湖图(丧心病狂的建图)
- sklearn学习笔记(二)——最近邻分类
- Java 之NIO(五) - 非阻塞式网络通信
- Java汉字md5值不一致问题
- 一位复旦微电子牛人的模电学习成长之路
- MemCache深度解读
- 设计形式评审流程规范图