1 条题解

  • 0
    @ 2026-9-28 11:23:53

    P6771

    这是一道很明显的 dp 问题。

    首先 dp 最重要的三要素是:动态表示、动态转移、初始状态。
    只要这三个要素搞明白了,基本就能把这题做出来了。

    solution

    让我们来看看这题的动态表示、动态转移和初始状态。

    状态表示:
    dpi,jdp_{i,j} 表示用前 ii 种方块是否可以拼成高度 jj

    状态转移:
    $dp_{i,j}= \begin{cases}\\\\\\\\\\\end{cases} \begin{matrix} dp_{i-1,j} && \text{用}0\text{块第}i\text{种方块}\\ dp_{i-1,j-h_{i}} && \text{用}1\text{块第}i\text{种方块}\\ &\ldots&\\ dp_{i-1,j-k\times h_{i}} && \text{用}k\text{块第i种方块}\\ &\ldots&\\ dp_{i-1,j-c_{i}\times h_{i}} && \text{用}c_{i}\text{块第}i\text{种方块}\\ \end{matrix}$
    $dp_{i,j}|=dp{i,j-k\times h_{i}};(h_{i}\le j\le a_{i}, 1\le k\le c_i)$

    初始状态:
    dpi,j=false;dp0,0=truedp_{i,j}=\mathrm{false};dp_{0,0}=\mathrm{true}

    最后物品维可以直接省掉,即:
    $dp_{j}|=dp_{j-k\times h_{i}};(h_{i}\le j\le a_{i}, 1\le k\le c_i)$

    那么写出这三要素就很容易写出代码了

    code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<string>
    #define line cout << endl
    using namespace std;
    
    const int NR = 405;
    struct node {
    	int h, a, c;
    };
    node e[NR];
    int n;
    bool dp[40005];
    
    bool cmp (node x, node y) {
    	return x.a < y.a; 
    }
    
    int main () {
    	cin >> n;
    	for (int i = 1; i <= n; i++)
    		cin >> e[i].h >> e[i].a >> e[i].c;
    	dp[0] = true;
    	sort (e + 1, e + n + 1, cmp);
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= e[i].c; j++) {
    			for (int k = e[i].a; k >= e[i].h; k--) {
    				dp[k] |= dp[k - e[i].h];//动态转移方程
    			}
    		}
    	}
    	for (int i = e[n].a; i >= 0; i--) {
    		if (dp[i]) {
    			cout << i << endl;
    			break;
    		}
    	}
    	return 0;
    }
    
    • 1

    [USACO05MAR] Space Elevator 太空电梯

    信息

    ID
    2305
    时间
    1000ms
    内存
    128MiB
    难度
    7
    标签
    递交数
    16
    已通过
    11
    上传者