贪心经典题目(部分背包)洛谷1016提高难度

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

输入格式

第一行,D1D1,CC,D2D2,PP,NN。

接下来有NN行。

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

输出格式

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

输入输出样例

输入 #1复制

275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2

输出 #1复制

26.95

说明/提示

N \le 6N≤6,其余数字\le 500≤500

分析:本题是典型贪心,我们一直往前走只要保证当下所拥有的油价值最低且装满同时保证能到终点即可,多出的油到终点减去即可

对每一个点便利后面满油可以到达的点:

情况1:后面点中有油价比它低的点:到后将剩下油减去,全部换上更低价格的油

2.后面点中无更低油价的点但满油可直达终点:直接到终点减去剩余的油

3.后面点中无更低油价的点且满油不可直达终点:找到后面可到范围内油价最小点,加满油,注意这种情况不到掉剩余的

#include<bits/stdc++.h>
using namespace std;
double  d1,c,d2,p0,sum=0,p1=501,c1,add;
int n,i,j,f=0,f1=0,nowi;
struct node{
    double d,p;
}s[10];
bool cmp(node a,node b){
    return a.d<b.d; 
}
#define max(x,y) (x<y?y:x)
#define min(x,y) (x>y?y:x)//习惯而已,实际上maxmin本题没用到 
int main(){
    scanf("%lf%lf%lf%lf%d",&d1,&c,&d2,&p0,&n);
    if(n==0){
        if(c*d2<d1){
            printf("No Solution");
        }
        else if(c*d2>=d1){
            sum=d1*p0/d2;
            printf("%.2lf",sum);
        }
    }//区分n是不是为0 
    else if(n!=0){
        for(i=1;i<=n;i++){
            scanf("%lf%lf",&s[i].d,&s[i].p);
        }
        sort(s+1,s+1+n,cmp);
        s[0].d=0; 
        s[0].p=p0;
        s[n+1].d=d1;
        for(i=1;i<=n+1;i++){
            if(((s[i].d-s[i-1].d)/d2)>c){
                f=1;
            }
        }
        if(f==1){
            printf("No Solution");//判断是否能有解
        }
        else if(f!=1){
            c1=c;
            sum+=s[0].p*c;
            p1=s[0].p;
            i=0;
            while(i<=n){
                p1=501;
                f1=0;
                for(j=i+1;j<=n;j++){
                    if(c*d2>(s[j].d-s[i].d)){
                        if(s[j].p<p1){
                            p1=s[j].p;
                            nowi=j;
                        }
                    }//为情况3铺垫,记录范围内最小 
                    if((s[j].p<s[i].p)&&(c*d2>(s[j].d-s[i].d))){
                        f1=1; 
                        add=c-((s[j].d-s[i].d)/d2);
                        sum=sum-add*s[i].p+s[j].p*c;;
                        i=j;//情况1 
                    }
                    if(f1==1){
                        break;
                    }
                }
                if(f1==0){
                    if(c*d2>(s[n+1].d-s[i].d)){
                        add=c-((s[n+1].d-s[i].d)/d2);
                        sum-=add*s[i].p;
                        i=n+1;//情况2 
                    }
                    else if(c*d2<=(s[n+1].d-s[i].d)){
                        add=c-((s[nowi].d-s[i].d)/d2);
                        sum+=(c-add)*s[nowi].p;
                        i=nowi;//情况3 
                    }
                }
            } 
            printf("%.2lf",sum);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值