1 条题解

  • 0
    @ 2026-10-27 12:58:42

    思路与算法

    用dp[i][j]表示氧气达到i、氮气达到j时的最低重量,超过需求的气量分别截断为m,n。初态dp[0][0]=0,其余无穷。每个气缸只处理一次,i,j都从大到小枚举,将旧状态更新到min(m,i+a)、min(n,j+b),代价加重量。最后读dp[m][n],无穷输出-1。

    正确性说明

    截断气量只合并已经达到相应需求的状态,不改变任何后续气缸能否达标。每个气缸加入或不加入覆盖所有子集;目标坐标不小于原坐标,倒序保证读取的状态尚未使用本气缸。截断导致的自环有正重量,不会改善原状态,故不产生重复使用。按气缸数归纳,所有状态都是最低重量,目标状态即所求。

    复杂度

    初始化O(mn),每个气缸枚举(m+1)(n+1)个状态,时间O(kmn),空间O(mn)。最大总重量不超过800000,普通int足够;无穷哨兵取大于此上界的值。

    易错点

    两种气体必须同时至少达标;气缸不可无限选。要双重倒序,不能只倒序一个维度。超过需求的气体要截断,否则会漏掉有用的大气量气缸。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int m, n, k;
        cin >> m >> n >> k;
        const int INF = 1000000000;
        vector<vector<int>> d(m + 1, vector<int>(n + 1, INF));
        d[0][0] = 0;
        while (k--) {
            int a, b, c;
            cin >> a >> b >> c;
            for (int i = m; i >= 0; --i)
                for (int j = n; j >= 0; --j) {
                    int x = min(m, i + a), y = min(n, j + b);
                    d[x][y] = min(d[x][y], d[i][j] + c);
                }
        }
        cout << (d[m][n] == INF ? -1 : d[m][n]) << "\n";
    }
    
    • 1

    信息

    ID
    2063
    时间
    1000ms
    内存
    64MiB
    难度
    普及+
    标签
    递交数
    0
    已通过
    0
    上传者