编程做题记录
贪心与优先队列

我们可以按以下步骤解决:
- 将工作按截止时间从小到大排序
- 使用优先队列维护已选工作,保证队列中工作总时间不超过截止时间
- 对于每个工作,若能插入队列则插入,否则替换掉队列中报酬最低的工作
还要注意工作时间不能超出选择的工作里面最大的截至时间
#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

月赛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;
}
}
}

浙公网安备 33010602011771号