4.4 贪心
4.4 贪心
http://codeup.hustoj.com/contest.php?cid=100000584
C To Fill or Not to Fill

题目释义
从杭州开始开车,车内没有油。给定若干加油站信息,问能否驾驶汽车行驶到目的地。若能行驶到目的地,则计算最小花费。若不能,则最远能够行驶多长距离。
给出的第一行数据为,油箱大小Cmax、杭州到目的地距离D、每单位油能行驶的距离Davg、加油站数目N
接下来的N行为各加油站信息,每单位油的价格、加油站离杭州的距离
题目解析
这道题的注意点在于:
-
加油时要注意车内可能还有剩余的油。
-
若接下来能到达的加油站价格都比现在加油站价格高,不能直接到下一站!!(这里WA了半天),而是要到能到达的相对价格最低的加油站。
所以在for语句中要记录接下来能到达站点中最低价格的加油站。
首先是审题,从杭州开往目的地,中间有n个加油站,一开始的车没有油,也就是起点必须是加油站,然后寻找加油量最少的站到达,并加油,最后到达目的地,如果两站之间隔得太远不能到,那就在能到的站加满油,走最大距离.
整体分析:
-
因为车从杭州出发,给出的加油站信息时加油站离杭州的距离。则假设杭州在起点,d=0。
-
将所有加油站按距离排序,从距离为0的起点出发,并把终点标记为离初始点距离为d,油价为0的点(油价为零可以优先被选成终点)
-
因为车一开始没有油,则若没有距离为0的加油站,则不能开车,能行驶的距离为0【游戏结束🙃️】
-
若能顺利发车,则有以下情况:
-
在当前加油站能到达的站中,能找到比当前站点油价更低的站点
则,在当前加油站加刚好能到此站点的油,因为到下一站能加的油更便宜【⚠️若车当前的有够这些,就不用加油了】
-
若不能找到比当前站点油价更低的站点,就找能到达的 价格相对最低 的站点
此时要加满油【因为当前站点的油比下一站点的油更便宜】
-
若根本找不到能到达的站点,则不能到达目的地了,则只能在当前加油站加满油能开多远开多远,故能行驶的最大距离为当前距离+油箱油量*每单位油能到达的距离【游戏结束🙈】
-
代码
#include <cstdio>
#include <algorithm>
using namespace std;
//假设杭州在起点0
struct station {
double p;//每升油价格
double d;//加油站起点位置
} s[505];
bool cmp(station a, station b) {
if (a.d != b.d) return a.d < b.d; //按照加油站距离从小到大排
else return a.p < b.p; //若距离相同,按照油价从小到大排
}
//贪心 每次都选择最好的
//如果没有第0站则直接到不了,X=0
//若排序后,遍历能到达的加油站,若有比当前站油价便宜的,就在当前站加刚刚好到此站点的油(注意可能原本车里有油)
//若没有比当前站便宜的,也要找一个相对价格最低的!!!(WA:不能直接到下一站),需在当前站加满油
int main() {
double capacity, distance, d_avg;
int n;
while (scanf("%lf %lf %lf %d", &capacity, &distance, &d_avg, &n) != EOF) {
for (int i = 0; i < n; i++) {
scanf("%lf %lf", &s[i].p, &s[i].d);
}
s[n].p = 0, s[n].d = distance;
sort(s, s + n + 1, cmp);
if (s[0].d != 0) {
printf("The maximum travel distance = 0.00\n");
return 0;
}
int curr_sNo = 0, next_sNo;
double max_d = capacity * d_avg, curr_capacity = 0, sum_p = 0, temp_minp;
while (curr_sNo < n) {
next_sNo = -1; //当前下一站点
temp_minp = 0x3fffffff; //当前能找到的最低油价
// 找出能到达站中最低的油价
for (int i = curr_sNo + 1; i <= n && s[i].d <= s[curr_sNo].d + max_d; i++) {
if (s[i].p < temp_minp) {
temp_minp = s[i].p;
next_sNo = i;
//若能找到低于当前油价的加油站,直接选择这个
if (temp_minp < s[curr_sNo].p) break;
}
}
//没有能到达的站点,则在当前站点加满油
if (next_sNo == -1) break;
else {
double need = (s[next_sNo].d - s[curr_sNo].d) / d_avg;
//找到低于当前油价的加油站,则加刚好到达此加油站的油
if (s[next_sNo].p < s[curr_sNo].p) {
if (need > curr_capacity) {
sum_p += (need - curr_capacity) * s[curr_sNo].p;
curr_capacity = 0;
} else {
curr_capacity -= need;
}
}
//没找到低于当前油价的加油站,则在当前加站满油到目前能到达的最低价格油站next_sNo
else {
sum_p += (capacity - curr_capacity) * s[curr_sNo].p;
curr_capacity = capacity - need;
}
curr_sNo = next_sNo;
}
}
if (curr_sNo < n) printf("The maximum travel distance = %.2f\n", s[curr_sNo].d + max_d);
else printf("%.2f\n", sum_p);
}
return 0;
}
F 迷瘴

题目解析
本题WA点在于计算当前液体和另一瓶液体混合时,当前液体的体积不一定为V。
WA时认为既然每瓶液体的体积都相同为V,则混合后浓度为二者浓度之和/2: tempp = (tempp + p[i]) / 2; 忽略了当前液体可能是混合很多次之后的,即当前液体体积不一定为V。故正确计算为: tempp = (tempp * ansv + p[i] * v) / (ansv + v);
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int main() {
int c;
int n, v, w, p[105];
scanf("%d", &c);
while (c--) {
scanf("%d %d %d", &n, &v, &w);
for (int i = 0; i < n; i++) {
scanf("%d", &p[i]);
}
sort(p, p + n);
if (p[0] > w) printf("0 0.00\n");
else {
int i, ansv = v;
double tempp = p[0], ansp = p[0];
for (i = 1; i < n; i++) {
tempp = (tempp * ansv + p[i] * v) / (ansv + v); //计算浓度要当心!!我以为浓度都是相加/2但是容积不总是相等
if (tempp > w) break;
else {
ansp = tempp;
ansv += v;
}
}
printf("%d %.2f\n", ansv, ansp / 100);
}
}
return 0;
}
本文作者:Joey-Wang
本文链接:https://www.cnblogs.com/joey-wang/p/14541167.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步