沪粤联赛 2025年3月月赛Div-2

问题 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;
}
posted @ 2025-03-31 20:54  Easoncalm  阅读(9)  评论(0)    收藏  举报