[NOIP1999 提高组] 旅行家的预算

题目传送门

分析

考虑N最多取6的话,dfs暴力和直接贪心模拟都是可以过的
思路:
 1.首先判断在起点和各个加油站是否能到达下一个加油站或终点
 2.考虑每到一个加油站为一个状态,首先要找到当前状态能到达的加油站有哪些
 3.在能到达的加油站中,如果有油费小于当前加油站的,直接加刚好能到那个加油站的油,如果有多个,先去最近的那一个(贪心)
 4.如果没有油费小于当前加油站的,就去其中油费最少的加油站(贪心)
其中处理到终点还有细节见代码

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define rg register
inline int read(){
    rg int x = 0, f = 1;
    rg char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}
double d1, c, d2;
int n;
struct node{
    double d, p;
    node(double x = 0, double y = 0){
        d = x;
        p = y;
    }
    bool operator<(const node& a) const{
        return d < a.d;
    }
}a[9];

inline void init(){
    cin >> d1 >> c >> d2 >> a[0].p >> n;
    for (int i(1); i <= n; ++i){
        cin >> a[i].d >> a[i].p;
        if (a[i].d - a[i - 1].d > c * d2){    //思路第一点
            printf("No Solution");
            exit(0);
        }
    }
    a[n + 1].d = d1;
    a[n + 1].p = 501;
}
inline void doit(){
    sort(a + 1, a + 1 + n);    //有一点多余但不重要
//    for (int i(0); i <= n+1; ++i)
//        printf("%f,%f\n", a[i].d, a[i].p);
    int i, j, k;
//    int cnt = 0;
//    int tot = 0;
    double cost = 0, left = 0;
    for (i = 0; i <= n;){
        for (j = i + 1; j <= n + 1; ++j){
            if (a[j].d - a[i].d > c * d2){      //思路第二点
                --j;
                break;
            }
        }
        if (j == n + 2) j--;        //这里是对能到终点的一个小处理
//        printf("%d : %d\n", ++tot, j);
        int flag = 0, net;
        double minp = 501;              //就是这个地方卡了一个小时,minp之前用的int定义
        for (k = i + 1; k <= j; ++k){
            if (a[k].p < a[i].p){
                flag = 1;
                break;
            }
            if (minp > a[k].p){      //思路第四点
                minp = a[k].p;
                net = k;
            }
        }
        if (flag){                      //思路第三点
            cost += ((a[k].d - a[i].d) / d2 - left) * a[i].p;
            left = 0;
            i = k;
 //           printf("f%d: %d:%f\n",++cnt,i,left);
        }
        else {
            if (j == n + 1){                //处理到终点
                cost += ((a[j].d - a[i].d) / d2 - left) * a[i].p;
                i = n + 1;
//                printf("ff%d: %d: %f\n",++cnt,i,left);
            }
            else {
                cost += a[i].p * (c - left);        //思路第四点的处理
                left = c - (a[net].d - a[i].d) / d2;
                i = net;
//                printf("fff%d: %d:%f\n",++cnt,i,left);
            }
        }
    }
    printf("%.2lf", cost);
}
int main(){
    ios::sync_with_stdio(false);
    cout.tie(NULL);
    init();
    doit();
    return 0;
}

posted @   ancer  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示