编程做题记录

贪心与优先队列
image
我们可以按以下步骤解决:

  • 将工作按截止时间从小到大排序
  • 使用优先队列维护已选工作,保证队列中工作总时间不超过截止时间
  • 对于每个工作,若能插入队列则插入,否则替换掉队列中报酬最低的工作
    还要注意工作时间不能超出选择的工作里面最大的截至时间
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;

struct Job {
    int t, d, p;
    bool operator<(const Job& other) const {
        return d < other.d;
    }
};

int main() {
    int T;
    cin >> T;
    
    while (T--) {
        int N;
        cin >> N;
        
        Job jobs[5005];
        for (int i = 0; i < N; i++) {
            cin >> jobs[i].t >> jobs[i].d >> jobs[i].p;
        }
        
        // 按截止时间排序
        sort(jobs, jobs + N);
        
        // 小根堆的定义,存储已选工作的报酬
        priority_queue<int, vector<int>, greater<int>> heap;
        long long total_time = 0;
        long long total_pay = 0;
        
        for (int i = 0; i < N; i++) {
            total_time += jobs[i].t;
            heap.push(jobs[i].p);
            total_pay += jobs[i].p;
            
            // 如果总时间超过截止时间,移除报酬最小的工作
            while (total_time > jobs[i].d) {
                total_pay -= heap.top();
                total_time -= jobs[i].t;  // 移除当前工作的时间
                heap.pop();
            }
        }
        
        cout << total_pay << endl;
    }
    
    return 0;
}

对于结构体的sort自定义比较(或者使用优先队列,元素是结构体类型时)重载运算符的两种方法见
https://uvlucnh8giw.feishu.cn/wiki/ltc1qcspdykesszwk0ya5ltntcyh9s38p6l7d0t7dng?fromScene=spaceOverview

image

月赛bfs
思路就是两个bfs,先对洪水进行染色,然后人走的时候看与洪水走过某一点时的时间比是否更早,更早就能过去。
基本的实现就是用队列,比赛的时候其实反应过来用bfs了,但是忘了bfs怎么实现,只记得dfs,也没多想就硬写。
bfs的实现就是先把一个点周围能走一步的几个方向坐标入队,然后记录这几步都是上一回合+1回合的。
然后一直把能入队的入队,最后知道所有点都更新完。

#include<bits/stdc++.h>
using namespace std;

char a[500][500];
int f[500][500], xx[4] = {0, 0, -1, 1}, yy[4] = {1, -1, 0, 0};
int visf[500][500], viss[500][500];

struct Node {
    int x, y, t;
};

void bfsFlood(int fx, int fy, int n, int m) {
    memset(visf, 0, sizeof(visf));
    memset(f, 0x3f, sizeof(f)); // 初始化为无穷大
    
    queue<Node> q;
    q.push({fx, fy, 0});
    visf[fx][fy] = 1;
    f[fx][fy] = 0;
    //这里都是初始化
    while (!q.empty()) {
        Node cur = q.front();
        q.pop();
        
        for (int i = 0; i < 4; i++) {
            int nx = cur.x + xx[i];
            int ny = cur.y + yy[i];
            
            if (nx >= 1 && nx <= n && ny >= 1 && ny <= m) {
                if (a[nx][ny] != '#' && !visf[nx][ny]) {
                    visf[nx][ny] = 1;
                    f[nx][ny] = cur.t + 1;//这里时记录到这一格是第几回合
                    q.push({nx, ny, cur.t + 1});
                }
            }
        }
    }
}

int bfsEscape(int sx, int sy, int n, int m) {
    memset(viss, 0, sizeof(viss));
    
    queue<Node> q;
    q.push({sx, sy, 0});
    viss[sx][sy] = 1;
    
    while (!q.empty()) {
        Node cur = q.front();
        q.pop();
        
        // 检查是否到达边界
        if (cur.x == 1 || cur.x == n || cur.y == 1 || cur.y == m) {
            return cur.t;
        }
        
        for (int i = 0; i < 4; i++) {
            int nx = cur.x + xx[i];
            int ny = cur.y + yy[i];
            
            if (nx >= 1 && nx <= n && ny >= 1 && ny <= m) {
                if (a[nx][ny] != '#' && !viss[nx][ny]) {
                    // 人的到达时间必须严格小于洪水到达时间
                    if (cur.t + 1 < f[nx][ny]) {
                        viss[nx][ny] = 1;
                        q.push({nx, ny, cur.t + 1});
                    }
                }
            }
        }
    }
    
    return -1; // 无法逃生
}

int main() {
    int t;
    cin >> t;
    
    for (int i = 1; i <= t; i++) {
        memset(a, 0, sizeof(a));
        
        int m, n;
        int sx, sy, fx, fy;
        cin >> n >> m;
        
        for (int j = 1; j <= n; j++) {
            for (int k = 1; k <= m; k++) {
                cin >> a[j][k];
                if (a[j][k] == 'F') {
                    fx = j, fy = k;
                }
                if (a[j][k] == 'S') {
                    sx = j, sy = k;
                }
            }
        }
        
        // 计算洪水扩展时间
        bfsFlood(fx, fy, n, m);
        
        // 计算逃生最短时间
        int ans = bfsEscape(sx, sy, n, m);
        
        if (ans != -1) {
            cout << "Yes " << ans << endl;
        } else {
            cout << "No" << endl;
        }
    }
}
posted @ 2025-07-07 19:24  暂未成功人士  阅读(7)  评论(0)    收藏  举报