【動態規劃】P11188 「KDOI-10」商店砍價|普及+

本文涉及知識點

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 1vi?105
  • 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×10i?1+y,i是位數,x是最高位。刪除最高位,再刪除的成本是 v x + y v_x+y vx?+y,本題 v x ≤ 1 0 5 v_x \le10^5 vx?105,故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]+z?10j?vz?

動態規劃的初始值

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;金融領域的股價預測、電商用戶消費金額預估。 線性…