【PAT甲级】1033 To Fill or Not to Fill (25 分)(贪心,思维可以做出简单解)

题意:

输入四个正数C,DIS,D,N(C<=100,DIS<=50000,D<=20,N<=500),分别代表油箱容积,杭州到目标城市的距离,每升汽油可以行驶的路程,加油站数量。接下来输入N行数据,每行包括一个小数代表该加油站每升汽油的价格和该加油站距离杭州的距离。输出杭州到该城市的最小加油花费,如果到不了的话输出离开杭州的最远路程。

思路:

每次到一个加油站时都把油箱加满,如果加油站i油箱加满所能行驶的范围内有加油站j油价比i便宜,那么j位置的花费就为i位置的花费减去(油箱加满时的最大行驶范围减去加油站i与j之间的距离)这段路程所需要消耗的汽油的花费再加上一整箱油的花费;如果最大行驶范围内没有比i便宜的加油站,就找一个加油站k是范围内最便宜的,那么k位置的花费就为i位置的花费加上加油站i与k之间的距离这段路程所需要消耗的汽油的花费。中途如果在加油站x加满油后最大路程超过目标城市,就更新ans使得等于当前加油站x的花费减去这箱油跑完超出目标城市距离的油的花费,如果x加油站后有油价更便宜的加油站就继续寻找,如果没有的话直接break,已经是最优解了,后面油价贵的加油站加油后的价格会超出在x加油后直接跑到目标城市的价格。核心想法是贪心,另一种解法是根据该题DIS最大只有30000,可以以加油站的油价从高到低排序,计算出每公里所加油最便宜的价格,以公里为坐标从后向前扫如果有断点(该公里无油可加,前不着村后不着店,则直接输出当前所在公里位置),无断点则将1~DIS每一公里所需的油价相加即为答案,我认为这样贪心需要考虑的地方较少,处理起来比较清晰明了,代码有空再整一个附上。。。

trick:

第1个测试点包含了多个加油站坐标相同的数据。

第2个测试点包含了起点没有加油站的数据。

第4个测试点包含了有多个加油站距离目标城市的距离小于等于邮箱最大容积的行驶距离且距离目标城市越近的加油站油越贵。

第0,6个测试点包含了有多个加油站距离目标城市的距离小于等于邮箱最大容积的行驶距离且距离目标城市越近的加油站油越便宜。

以上数据来自我错误代码的猜测,希望能对卡数据点2或者4(划重点)的朋友有所帮助。

AAAAAccepted code:

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 double c,dis,d;
 5 int n;
 6 pair<double,double>a[507];
 7 double sum[507];
 8 int main(){
 9     cin>>c>>dis>>d>>n;
10     for(int i=1;i<=n;++i)
11         cin>>a[i].second>>a[i].first;
12     sort(a+1,a+1+n);
13     if(a[1].first>0){
14         cout<<"The maximum travel distance = 0.00";
15         return 0;
16     }
17     sum[1]=c*a[1].second;
18     double ans=2e18;
19     for(int i=1;i<=n;++i){
20         double mn=2e18;
21         int pos=0;
22         for(int j=i+1;j<=n;++j){
23             if(a[j].first-a[i].first>c*d)
24                 break;
25             if(a[j].second<a[i].second){
26                 pos=j;
27                 break;
28             }
29             if(a[j].second<mn){
30                 mn=a[j].second;
31                 pos=j;
32             }
33         }
34         if(!pos&&i<n){
35             cout<<"The maximum travel distance = ";
36             printf("%.2f",a[i].first+c*d);
37             return 0;
38         }
39         if(a[i].first+c*d>=dis){
40             ans=min(ans,sum[i]-(a[i].first+c*d-dis)/d*a[i].second);
41             int flag=0;
42             for(int j=i+1;j<=n;++j)
43                 if(a[j].second<a[i].second)
44                     flag=1;
45             if(!flag)
46                 break;
47         }
48         if(a[pos].second<a[i].second)
49             sum[pos]=sum[i]-(c*d-(a[pos].first-a[i].first))/d*a[i].second+a[pos].second*c;
50         else
51             sum[pos]=sum[i]+(a[pos].first-a[i].first)/d*a[pos].second;
52         if(i<n)
53             i=pos-1;
54     }
55     if(a[n].first+c*d<dis){
56         cout<<"The maximum travel distance = ";
57         printf("%.2f",a[n].first+c*d);
58     }
59     else
60         printf("%.2f",ans);
61     return 0;
62 }
保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
原文地址:https://www.cnblogs.com/ldudxy/p/11515967.html