POJ2431贪心(最少加油次数)

题意:
       给一个终点,然后给你一个卡车距离终点的距离,还有其他个加油站距离终点的距离,然后每走一个单位距离要花费一个单位油,卡车的邮箱是无限大的,而每个加油站的油量是有限的,整个路径是一个线性的,然后求到达终点的最少加油次数。


思路: 
      想了将近20分钟才想出来,哎! 我的方法是贪心,大体思路是这样,先给加油站排序,然后从离自己最紧的开始枚举,如果当前能到达该加油站,那么把改加油站存起来,如果到达不了,那么就从之前存的里面取一个油量最大的加油,增加了当前能到的最大程度(这个值期初是卡车的原始油量),如果还是到不了,再继续取,就这样一直进行到到达终点,或者是改从库存里面取最大的加油的时候发现库存没有加油站了为止,对于这个库存我是用优先队列模拟的,这个不固定,用什么都行,比如set,一次操作的时间复杂度都是log(n),最后别忘了两种特殊情况,就是不用加油直接可以到达终点,还有就是有可能所有加油站都必须加油(这个是小心忘记一个判断),当然如果写的好的话无形中就躲开了这两种易错点,比如虚拟终点0 0 啥的,就说这么多吧!下面是我的方法,写的比较挫!而且还很有可能和官方标程思路不一样,我的时间复杂度是O(n*log(n))的。对了!最后还有两点,一个是记得给加油站排个序,还有就是不存在比卡车还远的加油站,一开始想多了。


#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>


#define N 10000 + 100


using namespace std;


typedef struct
{
    int a ,b;
}P;


typedef struct NODE
{
    int x;
    friend bool operator < (NODE a ,NODE b)
    {
        return a.x < b.x;
    }
}NODE;


P p[N];


bool camp(P a ,P b)
{
    return a.a < b.a;
}


int  main ()
{
    int n ,i ,x ,y;
    scanf("%d" ,&n);
    for(i = 1 ;i <= n ;i ++)
    scanf("%d %d" ,&p[i].a ,&p[i].b);
    scanf("%d %d" ,&x ,&y);
    sort(p + 1 ,p + n + 1 ,camp);
    int nowsum = 0 ,mkok = 0 ,nowlen = y;
    if(y >= x) mkok = 1;
    priority_queue<NODE>q;
    NODE xin ,tou;
    while(!mkok && n >= 1)
    {
        if(nowlen >= x - p[n].a)
        {
            xin.x = p[n].b;
            q.push(xin);
            n --;
        }
        else
        {
            if(q.empty()) break;
            tou = q.top();
            q.pop();
            nowlen += tou.x;
            nowsum ++;
            if(nowlen >= x)
            {
                mkok = 1;
                break;
            }
        }
    }
    while(!mkok && !q.empty())
    {
        tou = q.top();
        q.pop();
        nowlen += tou.x;
        nowsum ++;
        if(nowlen >= x)
        {
            mkok = 1;
            break;
        }
    }
    if(!mkok) nowsum = -1;
    printf("%d\n" ,nowsum);
    return 0;
}





Problem D:汽车最少费用加油行驶 Description 给定一个 N*N 的方形网格, 设其左上角坐标为 (1, 1), X 轴向右为正, Y 轴向下为正, 每个方格边长为 1, 右下角坐标为 (N, N). 一辆已装满油的汽车从 (1, 1) 为起点出发驶向终点 (N, N). 在若干个网格交叉点处设有油库供汽车在行驶途中加油, 在起点与终点处不设油库. 汽车在行驶过程中遵守如下规则: 1. 只能沿网格边行驶, 装满油后能行驶 K 条网格边 2. 当行驶经过一条网格边时, 若其 X 坐标或 Y 坐标减小, 则应付费用 B, 否则免付费用 3. 在行驶过程中遇油库则应加满油并付加油费用 A 4. 在需要时可在网格点处增设油库, 并付增设油库费用 C (不含加油费用A) 上述各数中的 N, K, A, B, C 均为正整数. 求汽车从起点出发到达终点的一条所付费用最少的行驶路线所需要的费用. Input 输入数据的第一行是 N, K, A, B, C 的值, 2 ≤ N ≤ 100, 2 ≤ K ≤ 10. 第二行起是一个 N*N 的 0-1 方阵, 每行 N 个值, 至 N+1 行结束. 方阵的第 i 行第 j 列处的值为 1 表示在网格交叉点 (i, j) 处设置有一个油库, 为 0 时表示未设有油库. 各行相邻的两个数以空格分隔. Output 对于测试用例的输入数据, 在一行上输出最优行驶路线所需的费用, 即最小费用. Sample Input 9 3 2 3 6 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 Sample Output 12
/*问题描述:一辆汽车加满油后可行驶nkm ,旅途中有若干个加油站,设计一个有效的算法, * 指出应在哪些加油站停靠加油,使沿途加油次数最少。 *算法设计:对于给定的n和k个加油站位置,计算最少加油次数。 * 数据输入;由文件input.txt给出输入数据。第一行有2个正整数n和k, * 表示汽车加油后可以行驶的nkm,且旅途中有k个加油站, * 接下来的一行中有k+1个整数,表示第k个加油站与k-1个加油站之间的距离, * 第0个加油站表示出发地,汽车已加满油。第k+1个加油站表示目的地, *结果输出:将计算的最少加油次数输出到文件output.txt * 如果无法到达目的地则输出”no solution“. * 输入文件示例: 输出文件示例: * input.txt output.txt * 7 7 4 * 1 2 3 4 5 1 6 6 部分代码: void greedy(int d[],int n,int k) { int num = 0; int i=0; int s=0; for( i = 0;i n) { //当任意的两个加油站之间的距离大于了汽车的最大行驶距离N cout<<"no solution\n"<<endl; return; } } for( i = 0,s = 0;i n) { num++; s = d[i]; cout<<"加油的站点为: "<<i<<endl<<endl; } cout<<"s="<<s<<" "; cout<<"number="<<num<<endl<<endl; } cout<<"最终加油次数为:"<<num<<endl; } /* 运行结果: * 请输入汽车可行驶: * 7 * * 加油站的个数: * 7 * * 请输入各个站点之间的距离 * * 第0到1站点的距离为: * 1 * 第1到2站点的距离为: * 2 * 第2到3站点的距离为: * 3 * 第3到4站点的距离为: * 4 * 第4到5站点的距离为: * 5 * 第5到6站点的距离为: * 1 * 第6到7站点的距离为: * 6 * 第7到8站点的距离为: * 6 * s=1 number=0 * * s=3 number=0 * * s=6 number=0 * * 加油的站点为: 3 * * s=4 number=1 * * 加油的站点为: 4 * * s=5 number=2 * * s=6 number=2 * * 加油的站点为: 6 * * s=6 number=3 * * 加油的站点为: 7 * * s=6 number=4 * * 最终加油次数为:4 * 请按任意键继续. . . * *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值