UVa 11523 Recycling

news/2024/6/16 14:27:01 标签: 算法, 动态规划

本题是一道区间型动态规划题目。

本题与 UVa 10559 Blocks 类似,可以说是该题的简化版本。令 m [ i ] m[i] m[i] 表示第 i i i 个物品,定义状态 d p [ l ] [ r ] dp[l][r] dp[l][r] 表示移除区间 [ l , r ] [l,r] [l,r] 内的可回收物品所需的最少操作次数,那么对于区间 [ l , r ] [l,r] [l,r] 的最左侧的物品 m [ l ] m[l] m[l] 来说,如果它不是一个可回收物品,那么不需考虑,只需继续考虑区间 [ l + 1 , r ] [l+1,r] [l+1,r] 的最少操作次数。如果物品 m [ l ] m[l] m[l] 是一个可回收物品,有两种选择:

  • 立即将物品 m [ l ] m[l] m[l] 移除,此时最少操作次数为 1 + d p [ l + 1 ] [ r ] 1+dp[l+1][r] 1+dp[l+1][r]

  • 不立即移除 m [ l ] m[l] m[l],而是先闲置,转而移除 m [ l ] m[l] m[l] 右侧的若干可回收物品,等待出现一个类型与最左侧物品 m [ l ] m[l] m[l] 类型相同的物品 m [ k ] m[k] m[k] 时,选择将最左侧物品 m [ l ] m[l] m[l] 与此物品 m [ k ] m[k] m[k] 及其右侧同类型的可回收物品一并移除,此时最少操作次数为 d p [ l + 1 ] [ k − 1 ] + d p [ k ] [ r ] dp[l+1][k-1]+dp[k][r] dp[l+1][k1]+dp[k][r]。对于此种情况,如果在向右移除并等待出现一个类型与 m [ l ] m[l] m[l] 的类型相同的物品过程中,遇到了一个不可回收的物品,那么此时不必再继续向右扫描,可以终止,因为无法将不可回收的物品放到回收桶中,后续的物品移除过程可以单独作为动态规划的一个子任务看待。

最终动态规划的递推关系式为:

d p [ l ] [ r ] = m i n { d p [ l + 1 ] [ r ] + 1 , m i n { d p [ l + 1 ] [ k − 1 ] + d p [ k ] [ r ] , m [ k ] = = m [ l ] } } dp[l][r]=min\{dp[l+1][r]+1,min\{dp[l+1][k-1]+dp[k][r],m[k]==m[l]\}\} dp[l][r]=min{dp[l+1][r]+1,min{dp[l+1][k1]+dp[k][r],m[k]==m[l]}}

参考代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 110, INF = 0x3f3f3f3f;
int n, m[MAXN], dp[MAXN][MAXN];
int dfs(int l, int r) {
    if (l > r) return 0;
    if (~dp[l][r]) return dp[l][r];
    if (!m[l]) return dp[l][r] = dfs(l + 1, r);
    int a = dfs(l + 1, r) + 1;
    for (int i = l + 1; i <= r; i++) {
        if (!m[i]) break;
        if (m[i] == m[l]) a = min(a, dfs(l + 1, i - 1) + dfs(i, r));
    }
    return dp[l][r] = a;
}
int main(int argc, char *argv[]) {
    cin.tie(0), cout.tie(0), ios::sync_with_stdio(false);
    int T; cin >> T;
    for (int cs = 1; cs <= T; cs++) {
        cin >> n;
        string s;
        map<string, int> indexer;
        int cnt = 1;
        for (int i = 0; i < n; i++) {
            cin >> s;
            if ('A' <= s[0] && s[0] <= 'Z') m[i] = 0;
            else {
                if (indexer.count(s)) m[i] = indexer[s];
                else {
                    indexer[s] = cnt;
                    m[i] = cnt++;
                }
            }
        }
        memset(dp, -1, sizeof dp);
        cout << "Case " << cs << ": " << dfs(0, n - 1) << '\n';
    }
    return 0;
}

http://www.niftyadmin.cn/n/471790.html

相关文章

您应该多久更换洗衣机上的油封?

洗衣机油封是一种密封装置&#xff0c;可保护洗衣机内部部件免受水或污垢的影响。它位于洗衣机的滚筒和外桶之间&#xff0c;可防止水分或碎屑进入机器并引起腐蚀。油封是洗衣机的重要组成部分&#xff0c;可确保其正常运行和耐用性。 但是洗衣机的油封应该多久更换一次呢? 答…

【Android复习笔记】Handler机制(三)

怎么检查线程有耗时任务 耗时任务: 正常的,轻微阻塞 不正常的,严重阻塞 检测线程是否发生耗时任务的方案: 系统服务通过 Watchdog 实现 应用进程可以通过 BlockCanery 实现 WatchDog 的原理 WatchDog是干什么的? 检查是否发生了死锁 检查线程是否被任务blocked Watchdog…

网络安全合规-ISO 27701

ISO 27701是什么&#xff1f; 是ISO 27001和 ISO 27002的扩展内容&#xff0c;对建立、实施、维护和持续改进隐私信息管理系统&#xff08;PIMS&#xff09;的各项要求做出了规定&#xff0c;是首部针对隐私信息管理的国际标准。该标准概述了适用于个人可识别信息控制者和处理者…

RocketMQ集群的特点以及各种集群模式的介绍

文章目录 1.RocketMQ集群中各角色的作用2.RocketMQ集群模式的种类2.1.集群模式的特点2.2.RockerMQ集群种类 1.RocketMQ集群中各角色的作用 RockerMQ集群架构&#xff1a; Producer&#xff08;生产者&#xff09;需要将消息数据存储到MQ消息队列中&#xff0c;Producer会向Nam…

剖析float相加产生精度损失的原因

float相加产生精度损失的原因 一、什么是float类型及其特点1.1、float类型的定义和使用方法1.2、float类型的特点&#xff0c;包括精度限制 二、为什么会出现float相加精度损失2.1、计算机二进制存储浮点数的方式2.2、浮点数运算中的舍入误差2.3、累加多个小数时的误差累积 三、…

Centos7下tensorflow 2.12无法找到NVIDIA Tesla T4 GPU终极解决方法

目录 背景 系统信息 GPU信息 关键软件信息 问题现象 原因分析

多元分类预测 | Matlab麻雀算法(SSA)优化极限学习机(ELM)的分类预测,多特征输入模型。SSA-ELM分类预测模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 麻雀算法(SSA)优化极限学习机(ELM)的分类预测,多特征输入模型。SSA-ELM分类预测模型 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可出分类效果图,迭代…

Scala的foldLeft与foldRight详解

foldLeft与foldRight是特质TraversableOnce定义的高阶函数&#xff0c;直译过来为向左折叠和向右折叠。具体实现如下摘出的代码所示&#xff1a; trait TraversableOnce[A] extends Any with GenTraversableOnce[A] {deprecated("Use foldLeft instead of /:", &quo…