HDU - 1069 DP

本文介绍了一道编程题目的解决方案,该题目要求利用动态规划算法来确定多个长方体堆叠时能达到的最大高度,确保每个长方体的长和宽严格小于其下方的长方体。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Monkey and Banana

题目大意:

给你n种长方体,每种立方体都有个长宽高,每种立方体有无数个,让你选择任意立方体堆起来,要求上面的长和宽都严格小于下面的长和宽,问你最高能堆多高。

数据范围:

0<n300<n≤30,多组输入到n为0时结束输入。

解题思路:

每种立方体又可分为三种立方体,即一共有3n个立方体,而每个立方体由于不可能使得底面相同,所以最多只能选一个,这时就可以确定一个状态,dp[i]代表以第i个立方体为底时可得的最大高度,即第i个状态可从前i-1个状态转移过来,即

for(int j = 1; j < i; j++) {
    if(ans[i].a > ans[j].a && ans[i].b > ans[j].b) {
        dp[i] = max(dp[i], dp[j] + ans[j].c);//(其中ans[j].c为第j个块的高度)
    }
}

但是这样的话,如果大的底在前面的话就不能保证答案的正确,可以将数组重复3n次,那么每个数都能跑到,但是这样就导致复杂度接受不了,单n等于30是就接近1e8了,还是多组,果断TLE了,所以,可以对底边从小到大排序一下,保证小底在前,就能AC了。(仔细想想,确定了宽是从小到大,宽相同时长按小到大,是能保证答案正确的,因为假如当前立方体宽较小而长较长,那么即使将它的被访问顺序往后挪的话,那么即使长度能满足了,那么宽度便满足不了了)

AC代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 10000;
typedef long long LL;
LL dp[maxn + 5];
int n, tot;
struct NOOD {
    LL a, b, c;
}ans[maxn+ 5];
bool cmp(NOOD x, NOOD y) {
    if(x.a == y.a)return x.b < y.b;
    return x.a < y.a;
}
int main() {
    while(~scanf("%d", &n) && n) {
        int t = 0;
        LL Maxm = 0;
        memset(dp, -1, sizeof(dp));
        for(int i = 1; i <= n; i++) {
            LL x, y, z;
            scanf("%lld%lld%lld", &x, &y, &z);
            ans[++t].a = x, ans[t].b = y, ans[t].c = z;
            ans[++t].a = z, ans[t].b = x, ans[t].c = y;
            ans[++t].a = y, ans[t].b = z, ans[t].c = x;
        }
        for(int i = 1; i <= t; i++) if(ans[i].a > ans[i].b)swap(ans[i].a, ans[i].b);
        sort(ans + 1, ans + t + 1, cmp);
        dp[1] = ans[1].c;
        Maxm = dp[1];
        for(int i = 2; i <= t; i++) {
            dp[i] = ans[i].c;
            for(int j = 1; j < i; j++) {
                if(ans[i].a > ans[j].a && ans[i].b > ans[j].b) {
                    dp[i] = max(dp[i], dp[j] + ans[i].c);
                }
            }
            Maxm = max(Maxm, dp[i]);
        }
        printf("Case %d: maximum height = %lld\n", ++tot, Maxm);
    }
    return 0;
}

转载于:https://www.cnblogs.com/TRDD/p/9813535.html

内容概要:该研究通过在黑龙江省某示范村进行24小时实地测试,比较了燃煤炉具与自动/手动进料生物质炉具的污染物排放特征。结果显示,生物质炉具相比燃煤炉具显著降低了PM2.5、CO和SO2的排放(自动进料分别降低41.2%、54.3%、40.0%;手动进料降低35.3%、22.1%、20.0%),但NOx排放未降低甚至有所增加。研究还发现,经济性和便利性是影响生物质炉具推广的重要因素。该研究不仅提供了实际排放数据支持,还通过Python代码详细复现了排放特征比较、减排效果计算和结果可视化,进一步探讨了燃料性质、动态排放特征、碳平衡计算以及政策建议。 适合人群:从事环境科学研究的学者、政府环保部门工作人员、能源政策制定者、关注农村能源转型的社会人士。 使用场景及目标:①评估生物质炉具在农村地区的推广潜力;②为政策制定者提供科学依据,优化补贴政策;③帮助研究人员深入了解生物质炉具的排放特征和技术改进方向;④为企业研发更高效的生物质炉具提供参考。 其他说明:该研究通过大量数据分析和模拟,揭示了生物质炉具在实际应用中的优点和挑战,特别是NOx排放增加的问题。研究还提出了多项具体的技术改进方向和政策建议,如优化进料方式、提高热效率、建设本地颗粒厂等,为生物质炉具的广泛推广提供了可行路径。此外,研究还开发了一个智能政策建议生成系统,可以根据不同地区的特征定制化生成政策建议,为农村能源转型提供了有力支持。
HDU-3480 是一个典型的动态规划问题,其题目标题通常为 *Division*,主要涉及二维费用背包问题或优化后的动态规划策略。题目大意是:给定一个整数数组,将其划分为若干个连续的子集,每个子集最多包含 $ m $ 个元素,并且每个子集的最大值与最小值之差不能超过给定的阈值 $ t $,目标是使所有子集的划分代价总和最小。每个子集的代价是该子集最大值与最小值的差值。 ### 动态规划思路 设 $ dp[i] $ 表示前 $ i $ 个元素的最小代价。状态转移方程如下: $$ dp[i] = \min_{j=0}^{i-1} \left( dp[j] + cost(j+1, i) \right) $$ 其中 $ cost(j+1, i) $ 表示从第 $ j+1 $ 到第 $ i $ 个元素构成一个子集的代价,即 $ \max(a[j+1..i]) - \min(a[j+1..i]) $。 为了高效计算 $ cost(j+1, i) $,可以使用滑动窗口或单调队列等数据结构来维护区间最大值与最小值,从而将时间复杂度优化到可接受的范围。 ### 示例代码 以下是一个简化版本的动态规划实现,使用暴力方式计算区间代价,适用于理解问题结构: ```cpp #include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 10010; int a[MAXN]; int dp[MAXN]; int main() { int T, n, m; cin >> T; for (int Case = 1; Case <= T; ++Case) { cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> a[i]; dp[0] = 0; for (int i = 1; i <= n; ++i) { dp[i] = INF; int mn = a[i], mx = a[i]; for (int j = i; j >= max(1, i - m + 1); --j) { mn = min(mn, a[j]); mx = max(mx, a[j]); if (mx - mn <= T) { dp[i] = min(dp[i], dp[j - 1] + mx - mn); } } } cout << "Case " << Case << ": " << dp[n] << endl; } return 0; } ``` ### 优化策略 - **单调队列**:可以使用两个单调队列分别维护当前窗口的最大值与最小值,从而将区间代价计算的时间复杂度从 $ O(n^2) $ 降低到 $ O(n) $。 - **斜率优化**:若问题满足特定的决策单调性,可以考虑使用斜率优化技巧进一步加速状态转移过程。 ### 时间复杂度分析 原始暴力解法的时间复杂度为 $ O(n^2) $,在 $ n \leq 10^4 $ 的情况下可能勉强通过。通过单调队列优化后,可以稳定运行于 $ O(n) $ 或 $ O(n \log n) $。 ### 应用场景 HDU-3480 的问题模型可以应用于资源调度、任务划分等场景,尤其适用于需要控制子集内部差异的问题,如图像分块压缩、数据分段处理等[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值