首页 > 其他分享 >P11188 解题报告

P11188 解题报告

时间:2024-10-16 18:48:04浏览次数:1  
标签:10 num 报告 int ll 删掉 解题 P11188 dp

题目传送门

分享一下我做这道题是的心路历程。

首先感觉像是贪心,但是随便举了几个例子就推翻了,发现无论是先删掉 \(v\) 值小的,还是先删掉靠前且数值大的都不行。

策略的选择如此复杂,考虑 dp。

其实很容易就能发现数据范围的异样:\(v_i\le 10^5\),这告诉我们操作 \(2\) 最多只能操作最后的 \(5\) 个数。

因为 \(5\times 10^5>10^5\),而 \(6\times 10^5<10^6\),所以选超过 \(5\) 个数进行操作二一定不如操作一优。

自此,我们可以将题意转化为:

给定一个序列 \(s\),从 \(s\) 中选出一个子序列 \(\{a_1, a_2,\cdots,a_k\}\),使得 \(\overline{a_1a_2\cdots a_k} - \sum\limits_{i = 1}^kv_i\) 最小。

dp 的状态设计其实可以参考数据范围,设 \(n\) 为原数的长度,考虑状态设计为 \(dp_{i, j}\)。

一开始我想的是直接线性 dp,从前向后递推,同时记录下此时最优策略保留下来的数来辅助递推,但很快就发现连样例 \(2\) 的第一组数据都过不了。

错误 \(\texttt{Code:}\)

#include <cstring>
#include <iostream>

#define x first
#define y second

using namespace std;

const int N = 100010;
typedef long long ll;
typedef pair<ll, ll> PLL;
int cid, T;
int n;
char s[N];
int v[10];
PLL dp[N][6];

void solve() {
    scanf("%s", s + 1);
    n = strlen(s + 1);
    for(int i = 1; i < 10; i++) scanf("%d", &v[i]);
    ll sumcost = 0;
    for(int i = 1; i <= n; i++)
        sumcost += v[s[i] - '0'];
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= 5; j++)
            dp[i][j] = {1e18, 0};
    dp[0][0] = {0, 0};
    for(int i = 1; i <= n; i++) {
        int limit = min(i, 5);
        dp[i][0] = dp[i - 1][0];
        for(int j = 1; j <= limit; j++) {
            dp[i][j] = dp[i - 1][j];
            if(dp[i][j].x > dp[i - 1][j - 1].x + dp[i - 1][j - 1].y * 10 + s[i] - '0' - v[s[i] - '0'])
                dp[i][j] = {dp[i - 1][j - 1].x + dp[i - 1][j - 1].y * 10 + s[i] - '0' - v[s[i] - '0'], dp[i - 1][j - 1].y * 10 + s[i] - '0'};
        }
    }
    ll ans = 1e18;
    for(int i = 0; i <= min(5, n); i++)
        ans = min(ans, dp[n][i].x);
    printf("%lld\n", sumcost + ans);
}

int main() {
    scanf("%d%d", &cid, &T);
    while(T--) {
        solve();
    }
    return 0;
}

然后我就发现:正着 dp 是错的。

因为你正着 dp 的时候只会保留当前长度下最优的解,但它实际上是具有后效性的。

就是这组样例:

3158927982863528
41423 65081 37768 31661 5606 86055 71796 46535 92370

最优的策略是保留 \(19796\) 最后删,其余全用方法一删掉。

但如果正着这样 dp,那么当考虑前 \(8\) 位时,最优解是删掉 \(9796\),而删掉 \(1979\) 这个策略的就被覆盖掉了。但事实上最后用后者更新的答案是要比前者更优的。

但是倒着 dp 就没有后效性了!

原因就是如果倒着做,每次更新时直接加上 \(num_i\times 10^{j - 1}\) 再减去 \(v_{num_i}\) 就行了,各个贡献的计算是独立进行的。

那么新的状态定于就是:\(dp_{i, j}\) 表示从后往前考虑到第 \(i\) 位时,保留了 \(j\) 个数时的最小 \(num - \sum v\)。

状态转移方程:

\(dp_{i, j} = \min\{dp_{i + 1, j}, dp_{i + 1, j - 1} + num_i\times 10^{j - 1} - v_{num_i}\}\)

最后答案就是选取 \(0\sim 5\) 个留下来的最小值,加上全用方法一消除的代价。

\(\texttt{AC Code:}\)

#include <cstring>
#include <iostream>

#define x first
#define y second

using namespace std;

const int N = 100010;
typedef long long ll;
int cid, T;
int n;
char s[N];
int v[10];
ll dp[N][6];
int power10[10];

void solve() {
    scanf("%s", s + 1);
    n = strlen(s + 1);
    for(int i = 1; i < 10; i++) scanf("%d", &v[i]);
    ll sumcost = 0;
    for(int i = 1; i <= n; i++)
        sumcost += v[s[i] - '0'];
    for(int i = 0; i <= n + 1; i++)
        for(int j = 0; j <= 5; j++)
            dp[i][j] = 1e18;
    dp[n + 1][0] = 0;
    for(int i = n; i; i--) {
        dp[i][0] = dp[i + 1][0];
        int limit = min(5, n - i + 1);
        for(int j = 1; j <= limit; j++) {
            dp[i][j] = dp[i + 1][j];
            dp[i][j] = min(dp[i][j], dp[i + 1][j - 1] + (s[i] - '0') * power10[j - 1] - v[s[i] - '0']);
        }
    }
    ll ans = 1e18;
    for(int i = 0; i <= min(5, n); i++)
        ans = min(ans, dp[1][i]);
    printf("%lld\n", sumcost + ans);
}

int main() {
    scanf("%d%d", &cid, &T);
    power10[0] = 1;
    for(int i = 1; i < 10; i++)
        power10[i] = power10[i - 1] * 10;
    while(T--) {
        solve();
    }
    return 0;
}

标签:10,num,报告,int,ll,删掉,解题,P11188,dp
From: https://www.cnblogs.com/Brilliant11001/p/18470552

相关文章

  • 【开题报告+论文+源码】基于SSM的日日新汽车美容管理系统设计与实现
    项目背景与意义随着社会经济的发展和人民生活水平的提高,汽车已经成为现代家庭中不可或缺的交通工具。而随着汽车所有者对汽车外观的要求日益提高,汽车美容行业也得到了快速的发展。汽车美容行业不仅包括汽车洗车、护理和维修等传统服务,还衍生出了诸如车贴装饰、玻璃贴膜、镀膜......
  • 【开题报告+论文+源码】基于SpringBoot+Vue的学生成绩管理系统
    项目背景与意义在当今社会,科技的迅猛发展和互联网的广泛应用为各种领域的创新与发展提供了广阔的空间。特别是IT软件信息技术的崛起,已经成为连接买卖双方、推动商业活动高效进行的重要力量。电子商务不仅通过技术手段实现了交易的便捷化,还打破了地域和时间的限制,为全球范围内......
  • 必看!解读Salesforce最新AI趋势报告
    近年来,AI技术正在快速渗透到各行各业,尤其是在客户关系管理(CRM)领域。据Salesforce最新的《AI在CRM中的趋势》报告显示,尽管AI发展潜力巨大,但许多公司在接受这一新技术时仍然犹豫不决。如何解决数据、信任和伦理等关键问题,成为企业能否真正释放AI潜力的关键。员工在AI领域的“自我......
  • 【开题报告】基于Springboot+vue高校教师指导的毕业论文查询系统(程序+源码+论文) 计算
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高等教育的普及与深入,高校教师指导学生完成毕业论文已成为教育过程中不可或缺的一环。然而,传统的人工管理方式在应对大量毕业论文的提交、审核、......
  • 【开题报告】基于Springboot+vue电商系统(程序+源码+论文) 计算机毕业设计
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的迅猛发展,电子商务已成为现代商业活动的重要组成部分。近年来,电商行业在全球范围内持续扩张,不仅改变了消费者的购物习惯,也为企业提供......
  • 【开题报告】基于Springboot+vue猫咪交流平台的设计与实现(程序+源码+论文) 计算机毕业
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着宠物文化的兴起,猫咪作为家庭宠物的地位日益显著,越来越多的家庭选择猫咪作为生活的伴侣。然而,猫咪与人类之间存在天然的沟通障碍,猫咪无法用人类的......
  • 【含开题报告+文档+PPT+源码】基于ssm的在线考试系统
    开题报告随着信息技术的快速发展,传统的纸笔考试方式逐渐被现代化的在线考试系统所取代。基于SSM的在线考试系统是一种利用软件和网络技术来进行考试和评估的工具。它通过提供便捷、高效和安全的考试环境,为学生和教师带来了许多益处。本文将探讨基于SSM的在线考试系统的目......
  • 【开题报告】基于Springboot+vue英语四六级单词学习系统(程序+源码+论文) 计算机毕业设
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今全球化的教育环境中,英语作为国际交流的主要语言,其重要性日益凸显。对于我国大学生而言,英语四六级考试不仅是衡量英语水平的重要标尺,也是未来求......
  • 【含开题报告+文档+PPT+源码】音乐播放和推荐系统的设计与实现
    开题报告随着互联网的发展和智能设备的普及,人们对于音乐的需求越来越大。传统的音乐播放器已经无法满足人们多样化的需求,因此开发一个在线音乐推荐与播放平台具有重要的研究背景和实际意义。传统的音乐播放器只提供基本的音乐播放功能,无法根据用户的个性化需求进行音乐推荐。......
  • 【开题报告】基于Springboot+vue校园物品私人订制平台(程序+源码+论文) 计算机毕业设计
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展和高校校园生活的日益丰富,学生们对于个性化、便捷化的校园服务需求日益增长。传统的校园购物模式往往局限于固定的商店和商品,......