问题 A: 道路清扫
赛时思路
贪心思路,枚举位置。(比较方法为绝对值)
赛后思路
按照排序 \(D_i\) ,枚举 \(N\) 个垃圾的起点和终点,计算移动距离即可。
代码
#include <bits/stdc++.h>
using namespace std;int main() {freopen("clean.in","r",stdin);freopen("clean.out","w",stdout);int n, m;cin >> n >> m;int d[m];for (int i = 0; i < m; ++i) cin >> d[i];sort(d, d + m);int res = 1e9; for (int i = 0; i <= m - n; ++i) {int l = d[i], r = d[i + n - 1];int dist = l >= 0 ? r : (r <= 0 ? -l : min(r - 2*l, 2*r - l));if (dist < res) res = dist;}cout << res << endl;return 0;
}
问题 B: 滑动拼图
赛前思路
正向模拟暴力骗分。
赛后思路
直接模拟会超时。
反过来考虑,计算最后左上角的格子在上一次的位置,可以做到O(n)。
代码
#include <bits/stdc++.h>
using namespace std;struct Crystal { int x, y, c; };int main() {freopen("crystal.in","r",stdin);freopen("crystal.out","w",stdout);int Gx, Gy, N, F;cin >> Gx >> Gy >> N >> F;Crystal* c = new Crystal[N];for (int i = 0; i < N; ++i)cin >> c[i].x >> c[i].y >> c[i].c;int** dp = new int*[Gx+1];for (int x = 0; x <= Gx; ++x) {dp[x] = new int[Gy+1];for (int y = 0; y <= Gy; ++y)dp[x][y] = (x + y) * F;}for (int i = 0; i < N; ++i) {int xi = c[i].x, yi = c[i].y, ci = c[i].c;for (int x = Gx; x >= 0; --x) {for (int y = Gy; y >= 0; --y) {if (x >= xi && y >= yi) {int px = x - xi, py = y - yi;if (px <= Gx && px >= 0 && py <= Gy && py >= 0)if (dp[x][y] > dp[px][py] + ci)dp[x][y] = dp[px][py] + ci;}}}}cout << dp[Gx][Gy] << endl;for (int x = 0; x <= Gx; ++x) delete[] dp[x];delete[] dp;delete[] c;return 0;
}
问题 C: 水晶城
赛前思路
暴力枚举。
赛后思路
考虑 DP,设 $ dp_{x,y} $ 表示走到 \((x,y)\) 的最小费用,初始化时$dp_{x,y} = (x + y) \times F $。
对于每一颗移动水晶,刷新 DP 表,转移为$dp_{x-x_i,y-y_i}+c_i \rightarrow dp_{x,y} $。
要求的答案为\(dp_{G_x,G_y}\)。
代码
#include <bits/stdc++.h>
using namespace std;struct Crystal { int x, y, c; };int main() {freopen("crystal.in","r",stdin);freopen("crystal.out","w",stdout);int Gx, Gy, N, F;cin >> Gx >> Gy >> N >> F;Crystal* c = new Crystal[N];for (int i = 0; i < N; ++i)cin >> c[i].x >> c[i].y >> c[i].c;int** dp = new int*[Gx+1];for (int x = 0; x <= Gx; ++x) {dp[x] = new int[Gy+1];for (int y = 0; y <= Gy; ++y)dp[x][y] = (x + y) * F;}for (int i = 0; i < N; ++i) {int xi = c[i].x, yi = c[i].y, ci = c[i].c;for (int x = Gx; x >= 0; --x) {for (int y = Gy; y >= 0; --y) {if (x >= xi && y >= yi) {int px = x - xi, py = y - yi;if (px <= Gx && px >= 0 && py <= Gy && py >= 0)if (dp[x][y] > dp[px][py] + ci)dp[x][y] = dp[px][py] + ci;}}}}cout << dp[Gx][Gy] << endl;for (int x = 0; x <= Gx; ++x) delete[] dp[x];delete[] dp;delete[] c;return 0;
}