本文涉及知识点

C++动态规划

P11188 「KDOI-10」商店砍价

题目背景

English Statement. You must submit your code at the Chinese version of the statement.

您可以点击 这里 下载本场比赛的选手文件。

You can click here to download all tasks and examples of the contest.

密码 / Password:rAnHoUyaSuoBaoMimaNijuEdefAngsHa2)2$1)0(2@0!

本场比赛所有题目从标准输入读入数据,输出到标准输出。

题目描述

有一个正整数 n n n,保证其只由数字 1 ∼ 9 1\sim 9 19 构成。

你可以做任意多次如下操作:

  • 选择 n n n 的一个数位 x x x,花费 v x v_x vx 的代价删除它,注意,此时 n n n 的数位个数会减少 1 1 1 n n n 的值也会发生相应的变化;
  • 或者,花费 n n n 的代价把剩余的所有数位删除。

求把整个数删除的最小代价。

输入格式

从标准输入读入数据。

本题有多组测试数据。

输入的第一行包含一个正整数 c c c,表示测试点编号。 c = 0 c=0 c=0 表示该测试点为样例。

第二行包含一个正整数 t t t,表示测试数据组数。

对于每组测试数据:

  • 第一行一个正整数 n n n,表示这个数的初始值。
  • 第二行九个正整数 v 1 , v 2 , … , v 9 v_1,v_2,\dots,v_9 v1,v2,,v9,表示删除每个数位的代价。

输出格式

输出到标准输出。

对于每组测试数据:

  • 输出一行一个正整数,表示最小代价。

输入输出样例 #1

输入 #1

0
3
123
10 10 10 10 10 10 10 10 10 
1121
2 1 2 2 2 2 2 2 2
987654321
1 2 3 4 5 6 7 8 9

输出 #1

21
6
45

说明/提示

【样例 1 解释】

对于第一组测试数据,最优操作方案如下:

  • 删除数位 2 2 2,代价为 10 10 10,此时 n n n 变为 13 13 13
  • 删除数位 3 3 3,代价为 10 10 10,此时 n n n 变为 1 1 1
  • 删除 n n n 的剩余所有数位,代价为 1 1 1

总代价为 10 + 10 + 1 = 21 10+10+1=21 10+10+1=21,可以证明,这是代价的最小值。

对于第二组测试数据,一种最优操作方案如下:

  • 删除第一个数位 1 1 1,代价为 2 2 2,此时 n n n 变为 121 121 121
  • 删除最后一个数位 1 1 1,代价为 2 2 2,此时 n n n 变为 12 12 12
  • 删除数位 2 2 2,代价为 1 1 1,此时 n n n 变为 1 1 1
  • 删除 n n n 的剩余所有数位,代价为 1 1 1

总代价为 2 + 2 + 1 + 1 = 6 2+2+1+1=6 2+2+1+1=6

【样例 2】

见选手目录下的 bargain/bargain2.inbargain/bargain2.ans

这个样例满足测试点 3 ∼ 6 3\sim 6 36 的约束条件。

【样例 3】

见选手目录下的 bargain/bargain3.inbargain/bargain3.ans

这个样例满足测试点 11 11 11 的约束条件。

【样例 4】

见选手目录下的 bargain/bargain4.inbargain/bargain4.ans

这个样例满足测试点 17 , 18 17,18 17,18 的约束条件。

【样例 5】

见选手目录下的 bargain/bargain5.inbargain/bargain5.ans

这个样例满足测试点 23 ∼ 25 23\sim 25 2325 的约束条件。


【数据范围】

对于全部的测试数据,保证:

  • 1 ≤ t ≤ 10 1\le t\le 10 1t10
  • 1 ≤ n < 1 0 1 0 5 1\le n< 10^{10^5} 1n<10105
  • 对于任意 1 ≤ i ≤ 9 1\le i\le 9 1i9 1 ≤ v i ≤ 1 0 5 1\le v_i\le 10^5 1vi105
  • n n n 由数字 1 ∼ 9 1\sim 9 19 构成。
测试点 n < n< n< v i ≤ v_i\le vi特殊性质
1 1 1 100 100 100 1 0 5 10^5 105
2 2 2 1 0 3 10^3 103 1 0 5 10^5 105
3 ∼ 6 3\sim 6 36 1 0 18 10^{18} 1018 1 0 5 10^5 105
7 ∼ 9 7\sim 9 79 1 0 40 10^{40} 1040 1 0 5 10^5 105
10 10 10 1 0 1 0 5 10^{10^5} 10105 1 0 5 10^5 105 n n n 由至多一种数字构成
11 11 11 1 0 1 0 5 10^{10^5} 10105 1 0 5 10^5 105 n n n 由至多两种数字构成
12 , 13 12,13 12,13 1 0 1 0 5 10^{10^5} 10105 1 0 5 10^5 105 n n n 由至多三种数字构成
14 ∼ 16 14\sim 16 1416 1 0 1 0 3 10^{10^3} 10103 1 0 5 10^5 105 v 1 = v 2 = v 3 = ⋯ = v 9 v_1=v_2=v_3=\dots =v_9 v1=v2=v3==v9
17 , 18 17,18 17,18 1 0 1 0 5 10^{10^5} 10105 1 0 5 10^5 105 v 1 = v 2 = v 3 = ⋯ = v 9 v_1=v_2=v_3=\dots =v_9 v1=v2=v3==v9
19 , 20 19,20 19,20 1 0 100 10^{100} 10100 100 100 100
21 , 22 21,22 21,22 1 0 1 0 3 10^{10^3} 10103 1 0 3 10^3 103
23 ∼ 25 23\sim 25 2325 1 0 1 0 5 10^{10^5} 10105 1 0 5 10^5 105

动态规划

性质一:最后删除前,数位一定不超过5位。如果超过5位,直接删除的成本是:
x × 1 0 i − 1 + y x\times 10^{i-1}+y x×10i1+y,i是位数,x是最高位。删除最高位,再删除的成本是 v x + y v_x+y vx+y,本题 v x ≤ 1 0 5 v_x \le10^5 vx105,故i > 5时,删除最高位再删除时不劣解。
性质二:最后删除x,相当于节约 x 各位的成本 − x x各位的成本-x x各位的成本x,删除所有位的成本- max ⁡ ( 节约的成本 ) \max(节约的成本) max(节约的成本)便是答案。

动态规划的状态表示

dp[n][j]表示处理完s的后n位,保留了j位节约的最大成本。 n ∈ [ 0 , N ] , j ∈ [ 0 , 5 ] n \in[0,N],j\in[0,5] n[0,N],j[0,5]
空间复杂度: O(n)

动态规划的填表顺序

枚举前驱状态,和操作。n从0到N-1,j任意。

动态规划的转移方程

如果倒数第n各位数z不保留
dp[n+1][j] = dp[n][j]
如果保留:
d p [ n + 1 ] [ j + 1 ] = d p [ n ] [ j ] + z ∗ 1 0 j − v z dp[n+1][j+1] = dp[n][j] + z*10^j - v_z dp[n+1][j+1]=dp[n][j]+z10jvz

动态规划的初始值

dp[0][0] ,其它LLONG_MIN/2。

动态规划的范围值

sum - max(dp.back()) 。sum是直接删除所有位的成本和。

代码

核心代码

#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>#include <bitset>
#include <chrono>
using namespace std::chrono;
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5, T6, T7>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) >> get<6>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char  puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++; }//忽略空格和回车ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行		return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错			}m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};class Solution {
public:long long Ans(const string& s, vector<int>& v) {const int N = s.length();vector<long long > pre(6, LLONG_MIN / 2);pre[0] = 0;vector<int> p10 = { 1,10,100,1000,10'000,100'000 };for (int n = 0; n < N; n++) {const int z = s[N - 1 - n] - '0';auto cur = pre;//不保留for (int j = 0; j + 1 < 6; j++) {cur[j + 1] = max(cur[j + 1], v[z - 1] - p10[j] * z + pre[j]);}pre.swap(cur);}long long sum = 0;for (const auto& ch : s) {sum += v[ch - '1'];}return sum - *max_element(pre.begin(), pre.end());}
};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG	ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob;int c, t;cin >> c >> t;string s;for (int i = 0; i < t; i++) {	cin >> s;auto v = Read<int>(9);
#ifdef _DEBUG	//printf("M=%d", M);Out(s, ",s=");Out(v, ",v=");//Out(ss, ",ss=");//Out(ope, ",ope=");
#endif // DEBUG		auto res = Solution().Ans(s,v);cout << res << "\n";}return 0;
}

单元测试

TEST_METHOD(TestMlethod11){auto res = Solution().Ans("9", vector<int>{ 1,1,1,1,1,1,1,1,1 });AssertEx(1LL, res);}TEST_METHOD(TestMlethod12){s = "123", v = { 10,10,10,10,10,10,10,10,10 };auto res = Solution().Ans(s, v);AssertEx(21LL, res);}TEST_METHOD(TestMlethod13){s = "1121", v = { 2,1,2,2,2,2,2,2,2 };auto res = Solution().Ans(s, v);AssertEx(6LL, res);}TEST_METHOD(TestMlethod14){s = "987654321", v = { 1,2,3,4,5,6,7,8,9 };auto res = Solution().Ans(s, v);AssertEx(45LL, res);}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912899.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912899.shtml
英文地址,请注明出处:http://en.pswp.cn/news/912899.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产LHR3040芯片是REF5040的代替品

LHR3040是一款噪声低、漂移低、精度高的电压基准产品系列。这些基准同时支持灌电流和拉电流&#xff0c;并且具有出色的线性和负载调节性能。采用专有的设计技术实现了出色的温漂(3ppm/℃)和高精度(0.05%)。这些特性与极低噪声相结合&#xff0c;使LHR30XX系列成为高精度数据采…

专题:2025AI营销市场发展研究报告|附400+份报告PDF汇总下载

原文链接&#xff1a;https://tecdat.cn/?p42800 在数字化浪潮席卷全球的当下&#xff0c;AI营销正成为驱动企业增长的核心动力。 从市场规模来看&#xff0c;AI营销正经历着爆发式增长&#xff0c;生成式AI的出现更是为其注入了强大活力。在应用层面&#xff0c;AI已渗透到营…

深入对比 Python 中的 `__repr__` 与 `__str__`:选择正确的对象表示方法

文章目录 核心概念对比1. 根本目的差异2. 调用场景对比深入解析:何时使用哪种方法场景 1:开发者调试 vs 用户展示场景 2:技术表示 vs 简化视图高级对比:特殊场景处理1. 容器中的对象表示2. 日志记录的最佳实践3. 异常信息展示最佳实践指南1. 何时实现哪个方法?2. 实现原则…

万能公式基分析重构补丁复分析和欧拉公式原理推导

基分析&#xff0c; x11 x2-1 x3i 存在加法法则 x1x20 所以x1-x2 存在链式基乘法法则 x1x1*x1x2*x2 x2x3*x3 x3x1*x3 -x1x2x3 将链式基乘法操作 二次&#xff0c;三次&#xff0c;直至n次化简得 一次 x1 -x1 x3 矩阵 x1 x1 x2 x2 x3 …

OpenCV 4.10.0 移植

OpenCV 4.10.0 移植使用 概述移植编译下载解压编译环境编译 编译完成OpenCV 库文件及其作用 使用实例参考代码 参考 概述 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是计算机视觉领域最广泛使用的开源库之一&#xff0c;提供了丰富的功能模块&#xf…

Tomcat10.0以上版本编译成功但报错HTTP状态 404

Tomcat正常启动且项目已成功部署&#xff0c;但出现404错误。 HTTP状态 404 - 未找到package org.example;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpSer…

在Flask项目中用Git LFS管理大文件(PDF)的完整实践

在Flask项目中用Git LFS高效管理大文件(以农机说明书PDF为例) 背景与需求 在农机管理系统等实际项目中,经常需要上传和管理大量超大文件(如200MB以上的PDF说明书、图片等)。如果直接用Git管理这些大文件,不仅会导致仓库膨胀、clone/pull速度变慢,还可能遇到推送失败等…

朴素贝叶斯算法案例演示及Python实现

目录 一、基本原理二、案例演示2.1 未平滑处理2.2 Laplace平滑处理 三、Python实现 一、基本原理 朴素贝叶斯思想&#xff1a;依靠特征概率去预测分类&#xff0c;针对于代分类的样本&#xff0c;会求解在该样本出现的条件下&#xff0c;各个类别出现的概率&#xff0c;哪个类…

RAG从入门到高阶(二):Retrieve-and-Rerank

在上一篇教程中&#xff0c;我们了解了 Naive RAG 的基本原理和实现。它就像一个刚刚学会查找资料的新手&#xff0c;虽然能找到一些信息&#xff0c;但有时候找到的并不够精准&#xff0c;甚至会有一些无关的干扰。 今天&#xff0c;我们将介绍 Retrieve-and-Rerank RAG&…

【脚本】Linux磁盘目录挂载脚本(不分区)

以下是一个不带分区&#xff0c;直接挂载整个磁盘到指定目录的脚本。该脚本会检查磁盘是否已挂载&#xff0c;自动创建文件系统&#xff08;可选&#xff09;&#xff0c;并配置开机自动挂载&#xff1a; #!/bin/bash# 磁盘直接挂载脚本&#xff08;不分区&#xff09; # 使用…

壁纸网站分享

壁纸网站链接&#xff1a; 1.Microsoft Design - Wallpapers&#xff1a;https://wallpapers.microsoft.design/?refwww.8kmm.com 2.哲风壁纸&#xff1a;https://haowallpaper.com/wallpaperForum 3.壁纸湖&#xff1a;https://bizihu.com/ 4.极简壁纸&#xff1a;https://bz…

XILINX FPGA如何做时序分析和时序优化?

时序分析和时序优化是FPGA开发流程中关键步骤&#xff0c;确保设计在目标时钟频率下正确运行&#xff0c;避免时序违例&#xff08;如建立时间或保持时间不足&#xff09;。以下以Xilinx Kintex-7系列FPGA为例&#xff0c;详细介绍时序分析和时序优化的方法、工具、流程及实用技…

linux screen轻松管理长时间运行的任务

以下是针对 Alpine Linux 环境下 screen 的安装与使用指南&#xff0c;结合迁移数据场景的具体操作步骤&#xff1a; 1. 安装 screen‌ 在 Alpine Linux 中需通过 apk 安装&#xff08;非默认预装&#xff09;&#xff1a; apk add screen 验证安装&#xff1a; screen --…

VR制作公司业务范围

VR制作公司概念、能力与服务范围 虚拟现实&#xff08;Virtual Reality, VR&#xff09;技术&#xff0c;作为当代科技的前沿领域&#xff0c;通过计算机技术模拟出真实或虚构的世界环境&#xff0c;使用户能够沉浸其中并进行交互体验。VR制作公司&#xff0c;是这一领域的专业…

STM32之28BYJ-48步进电机驱动

目录 一、引言 二、28BYJ-48步进电机简介 2.1 基本特性 2.2 内部结构 2.3 工作模式 2.4 驱动原理 2.5 性能特点 2.6 驱动方案 2.7 使用注意事项 三、ULN2003驱动板简介 3.1 基本概述 3.2 电路结构 3.3 驱动原理 3.4 接口定义 3.5 使用注意事项 四、…

TDSQL如何查出某一列中的逗号数量

在 TDSQL 中&#xff0c;要统计某一列里逗号的数量&#xff0c;可借助字符串函数来实现。下面为你介绍具体的实现方法&#xff1a; sql SELECT your_column,LENGTH(your_column) - LENGTH(REPLACE(your_column, ,, )) AS comma_count FROM your_table;下面对这段 SQL 进行详细…

如何避免服务器出现故障情况?

服务器作为存储数据信息的重要网络设备&#xff0c;能够保护企业重要数据的安全性&#xff0c;但是随着网络攻击的不断拓展&#xff0c;各个行业中的服务器也会遭受到不同类型的网络攻击&#xff0c;严重的会导致服务器业务中断出现故障&#xff0c;给企业带来巨大的经济损失。…

C++ 优先级队列

一、引言 队列的特性是先进先出。优先级队列的本质是一个有序队列&#xff0c;根据成员的优先级&#xff0c;对队列中的成员进行排序。优先级队列默认是大顶堆&#xff0c;即堆顶元素最大 二、常用函数 empty()size()top()push()emplace()pop()swap() 三、代码示例 class …

学习笔记(27):线性回归基础与实战:从原理到应用的简易入门

线性回归&#xff1a;通过拟合线性方程&#xff08;如 \(y w_1x_1 w_2x_2 b\)&#xff09;预测房价、销售额等连续变量&#xff0c;需掌握特征标准化、正则化&#xff08;L1/L2&#xff09;防止过拟合。应用场景&#xff1a;金融领域的股价预测、电商用户消费金额预估。 线性…