zoukankan      html  css  js  c++  java
  • 洛谷 P1016 旅行家的预算 模拟+贪心

    题面

    题目链接

    P1016 旅行家的预算

    题目描述

    一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离 $ D_1 $ 、汽车油箱的容量 $ C $ (以升为单位)、每升汽油能行驶的距离 $ D_2 $ 、出发点每升汽油价格 $ P $ 和沿途油站数 $ N $ ( $ N $ 可以为零),油站i离出发点的距离 $ D_i $ 、每升汽油价格 $ P_i (i=1,2,...,N) $ 。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

    输入输出格式

    输入格式

    第一行,$ D_1,C,D_2,P,N $ 。

    接下来有 $ N $ 行。

    第 $ i+1 $ 行,两个数字,油站 $ i $ 离出发点的距离 $ D_i $ 和每升汽油价格 $ P_i $ 。

    输出格式

    所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

    输入输出样例

    输入样例

    275.6 11.9 27.4 2.8 2
    102.0 2.9
    220.0 2.2
    

    输出样例

    26.95
    

    说明

    $ N leq 6 $ , 其他数字 $ leq 500 $

    【时空限制】

    1000ms,128MB

    思路

    这道题还真有点麻烦。不过数据规模很小,乱搞搞应该是都能AC的。那我来介绍一种贪心的方法。

    首先不妨记起点为第0个加油站,终点为第N+1个加油站且加油价格为0,那么我们可以以如下方式贪心

    1.从当前点向后寻找加满油可到的,且油价比当前点小的点。如果当前点不加油可以到达,那么就走过去;否则需要多少油就加多少油(因为走过这个加油站就可以用当前加油站油价更低的油了,多加无用)

    2.如果找不到(1)中所述的加油站,那么向后寻找加满油可到的,且油价尽量低的点。然后加满油过去(如果不加满而选择到下一个点加油,那就浪费了)

    3.如果没有点可走,那就No Solution

    除此之外,如果到终点还有油,那么显然是浪费了。所以我们应该在上一个加油的地方少加一点油,这可以等效为把油带回去卖掉。故每次加油要记录上次加油的位置

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int n;
    double L,V,D;
    double d[8],w[8];
    double ans;
    
    int main()
    {
        cin>>L>>V>>D>>w[0]>>n;
        for(int i=1;i<=n;i++) cin>>d[i]>>w[i];
        d[n+1]=L,w[n+1]=0;
    
        int np=0,last=0;
        double nv=0;
        while(1)
        {
            int v;
            bool f=false;
            for(v=np+1;v<=n+1;v++)
            if(w[v]<w[np] && V>=(d[v]-d[np])/D)
            {
                if(nv>=(d[v]-d[np])/D) nv-=(d[v]-d[np])/D,np=v;
                else ans+=((d[v]-d[np])/D-nv)*w[np],np=v,nv=0,last=np;
                f=true;break;
            }
            if(!f)
            {
    
                double mi=1000000;
                int p=-1;
                for(v=np+1;v<=n+1;v++)
                    if(w[v]<mi && V>=(d[v]-d[np])/D) mi=w[v],p=v;
                if(p==-1) {cout<<"No Solution";return 0;}
                else ans+=(V-nv)*w[np],nv=V-(d[p]-d[np])/D,np=p,last=np;
            }
            if(np==n+1) break;
        }
        ans-=nv*w[last];
        printf("%.2f",ans);
        return 0;
    }
    

    总结

    1.遇到数据小的题要有多种思路

    2.要自己动手模拟

  • 相关阅读:
    layui镜像站文档
    mysql 查询 包含哪个字符串
    laydate时间点击后马上消失
    timer_dma_enable
    map文件堆栈大小
    回调函数
    复位电路
    stm32 map文件的分析
    如何在VSCode里面写代码进行调试和运行
    DMA为CPU减负
  • 原文地址:https://www.cnblogs.com/Mercury04/p/9762998.html
Copyright © 2011-2022 走看看