比赛地址
A. 小竹与妈妈
题意:
妈妈的年龄是小竹的 a 倍多 b,已知妈妈年龄为 x ,求小竹年龄
思路:
签到题,小竹年龄 = ( x - b ) / a
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define int long long
#define div cout << "--------------------------" << endl
const int N = 1e5 + 5;
typedef pair<int, int> PII;
int n, m;
int a[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int a, b, c;
cin >> a >> b >> c;
cout << (c - b) / a << endl;
return 0;
}
B. 走丢的小竹
题意:
n 个出口连着 m 个房间,已知有房间 k 有坏人,求有多少个出口能走
思路:
用 cnt 数组表示通向每个房间的的出口数,能走的出口数 = 总出口数 - 通向房间 k 的出口数即 n - cnt[ k ]
AC代码:
#include <bits/stdc++.h>
using namespace std;
// #define x first
// #define y second
#define int long long
#define div cout << "--------------------------" << endl
const int N = 1e5 + 5;
typedef pair<int, int> PII;
int a[N];
int b[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m, q;
cin >> n >> m >> q;
for (int i = 1; i <= n; i ++)
{
int t;
cin >> t;
a[t] ++; // 通往t房间的出口个数
}
while (q --)
{
int x;
cin >> x;
cout << n - a[x] << endl;
}
return 0;
}
C. 小竹关禁闭
题意:
n 个长度为 ai 物品选择若干个制作成绳子,要使得绳子总长度最长,限制:选了第 i 个物品后,其右边 k 个物品皆不能使用
思路:
DP
AC代码:
#include <bits/stdc++.h>
using namespace std;
// #define x first
// #define y second
#define int long long
#define div cout << "--------------------------" << endl
const int N = 1e5 + 5;
typedef pair<int, int> PII;
int a[N];
int f[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i ++) cin >> a[i];
f[n] = a[n];
for (int i = n - 1; i >= 1; i --)
f[i] = max(f[i + k + 1] + a[i], f[i + 1]);
cout << f[1] << endl;
return 0;
}
D.游戏购买!
题意:
n x m 的网格,要从起点先经过 特定点(可能不唯一) 再从特定点走向终点,求路径最小值
思路:
两遍 BFS
第一遍 BFS 求终点到所有点的路径最小值(必定包含到特定点的最小值),保存在 dist2[ N ] 中
第二遍 BFS 求起点到所有特定点的路径最小值为 dist1[ N ],再对所有的 dist1[ k ] + dist2[ k ] 求最小值
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define int long long
#define div cout << "--------------------------" << endl
const int N = 2000 + 5;
typedef pair<int, int> PII;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int n, m, t; // t 是刺激度
int x1, Y, x2, y2;
int g[N][N];
int dist[N][N];
int dist2[N][N];
void bfs2(PII start) // 从 start 到 end 的距离
{
queue<PII> q;
memset(dist2, -1, sizeof dist2); // 初始化
q.push(start); // 起点入队
dist2[start.x][start.y] = 0; // 到起点距离为 0
while (!q.empty())
{
auto item = q.front(); // 取队头
q.pop(); // 弹出队头
for (int i = 0; i < 4; i ++) // 扩展队头
{
int x = item.x + dx[i], y = item.y + dy[i]; // 下一步
if (x < 1 || x > n || y < 1 || y > m || g[x][y] == -1) continue; // 出界 或者 墙
if (dist2[x][y] != -1) continue; // 该点走过
dist2[x][y] = dist2[item.x][item.y] + 1; // 更新距离
q.push({x, y}); // 新点入队
}
}
}
int bfs(PII start)
{
queue<PII> q;
memset(dist, -1, sizeof dist); // 初始化
q.push(start); // 起点入队
dist[start.x][start.y] = 0;
int waY = 10000;
while (!q.empty())
{
auto item = q.front(); // 取队头弹出
q.pop();
for (int i = 0; i < 4; i ++) // 拓展队头
{
int x = item.x + dx[i], y = item.y + dy[i]; // 下一步
if (x < 1 || x > n || y < 1 || y > m || g[x][y] == -1) continue; // 出界 或者 墙
if (dist[x][y] != -1) continue; // 该点走过
dist[x][y] = dist[item.x][item.y] + 1;
if (g[x][y] > t) // 当前是刺激点
{
int now = dist[x][y]; // 从起点到当前刺激点距离为 now
// cout << "从起点到当前刺激点距离为:" << now << endl;
// cout << "当前刺激点为:" << x << ' ' << y << endl;
PII start2 = {x, y};
int way2 = dist2[x][y]; // 从当前终点到当前刺激点的路
// cout << "当前刺激点到终点距离为:" << way2 << endl;
if (way2 == -1) continue; // 如果从当前刺激点无法到达终点
else waY = min(waY, way2 + now);
}
q.push({x, y}); // 新点入队
}
}
if (waY == 10000) return -1;
else return waY;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> t;
cin >> x1 >> Y >> x2 >> y2;
PII start = {x1, Y};
PII end = {x2, y2};
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
cin >> g[i][j];
bfs2(end);
cout << bfs(start) << endl;
return 0;
}
E.寻找小竹!
题意:
思路:
AC代码: