披着信息的皮的数学题
题目描述
您有一个字符串a1,a2,…,ana1,a2,…,an,由零和一组成。
我们将连续元素ai,ai + 1,...,ajai,ai +1,...,aj(1≤i≤j≤n1≤i≤j≤n)的序列称为字符串aa的子字符串。
您可以多次应用以下操作:
选择一个字符串aa的子字符串(例如,您可以选择整个字符串)并反转它,为此支付xx个硬币(例如,«0101101»→→«0111001»);
选择字符串aa的一些子字符串(例如,您可以选择整个字符串或仅一个符号),然后将每个符号替换为相反的一个符号(零替换为一个,而一个替换为零),为此支付yy个硬币(例如,«0101101»→→«0110001»)。
您可以按任何顺序应用这些操作。允许将操作多次应用于同一子字符串。
您需要花费最少的硬币数量才能得到仅包含一个的字符串?
输入值
输入的第一行包含整数nn,xx和yy(1≤n≤300000,0≤x,y≤1091≤n≤300000,0≤x,y≤109)—字符串的长度,第一次操作的成本(反向子串)和第二个操作的成本(反向子串的所有元素)。
第二行包含长度为nn的字符串aa,由零和一组成。
输出量
打印一个整数-获得只包含1的字符串所需的最低总操作成本。如果不需要执行任何操作,请打印00。
例子
输入值
5 1 10
01000
输出量
11
输入值
5 10 1
01000
输出量
2
输入值
7 2 3
1111111
输出量
0
注意
在第一个示例中,首先需要反转子字符串[1…2] [1…2],然后需要反转子字符串[2…5] [2…5]。
然后,字符串更改如下:
«01000»→→«10000»→→«11111»。
运营总成本为1 + 10 = 111 + 10 = 11。
在第二个示例中,首先需要反转子字符串[1…1] [1…1],然后需要反转子字符串[3…5] [3…5]。
然后,字符串更改如下:
«01000»→→«11000»→→«11111»。
总成本为1 + 1 = 21 + 1 = 2。
在第三个示例中,字符串已经仅包含一个,因此答案为0。
思路分析:
看这道题,脑子里立马就蹦出了DP,前两道题也都是DP,就坚信这道题得这么做了,然后就懵了
这道题看起来简洁明了,就是一个只有0和1的字符串,然后对其进行两种操作:区间内前后翻转和把区间内0全变为1。然后求把整个字符串全变为1的最小代价。
恶心的地方就在这两种操作都可以执行上了,有点无从下手。
没办法,分析样例。不难发现,可以对数据进行分组,即把多个连在一起的0或1视为一个整体进行处理(显然这样可以尽可能少的处理,代价最小),然后对每组0进行考虑,这时候的字符串形式就是类似于0101010……这样的
我们的最终目的是要把0变为1,你再怎么换,你也少不了变为0的操作——划重点,代码会体现
我们考虑每两个相邻的0101,发现有两种方法处理:(1)转一下前面的01,变为1001;然后进行修改,变为1111;(2)进行两次修改,变为1111;
我们发现,其中都有一次修改操作,那我们比较另一个不同的即可,显然谁代价小选哪个,不管你选哪个,都不需要再考虑这前面的一组,如果你变为1了,显然不用再管了,如果你选择了转换,那前面的0和后面的0就成一组0了,接下来再只考虑后面的就可以了。如果你着这样我们就合并了两个相邻的;
接下来,数组还是101010……的形式,继续进行如下操作,每组01都是这样,那就简单了,如果有n组01,我们把最后一次转化为1的操作单独拿出来,剩下的n-1组我们只需进行(n-1)次的单一操作——两种操作哪个小选哪个。
配合代码理解(不懂一定要自己模拟一遍样例,体会一下过程):
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 3e5+10; 7 char a[maxn]; 8 long long tot; 9 int main(){ 10 long long n,x,y;scanf("%lld%lld%lld ",&n,&x,&y); 11 scanf("%s",a+1); 12 a[0] = '1'; 13 for(int i = 1; i <= n;i++){ 14 if(a[i] == '0' && a[i-1] == '1')tot++; //出现不相邻的0,就多了一组01,否则与前面的0为同一组 15 } 16 if(tot == 0)printf("0"); 17 else printf("%lld",min(x,y) * (tot-1) + y); //前tot-1组,单一操作合并为一组,最后再加上一次统一修改的操作 18 return 0; 19 }
这就是一个数学题...
原文地址:https://www.cnblogs.com/hhhhalo/p/12681304.html
- 使用concurrent.futures模块并发,实现进程池、线程池
- 人工智能与医疗
- 每周论文清单:知识图谱,文本匹配,图像翻译,视频对象分割
- 进程池、线程池、回调函数
- java学习:weblogic下JNDI及JDBC连接测试(weblogic环境)
- 简单谈谈python的反射机制
- java学习:使用dom4j读写xml文件
- python文件和目录操作方法大全
- 自动驾驶汽车伦理大讨论:到底谁有权决定他人的生死?
- 异常处理:1215 - Cannot add foreign key constraint
- pymysql模块
- oracle 11g 查看服务端/客户端编码,及修改db编码
- PHP7 下的协程实现
- mysql数据备份与恢复
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- NeurIPS 2020 | 一种崭新的长尾分布下分类问题的通用算法
- 精解四大集合框架:Map核心知识总结
- 厉害了,Matplotlib还能这样画散点图!
- 20种小技巧,玩转Google Colab
- 不用try catch,如何机智的捕获错误
- StyleGAN2玩出新高度!从华盛顿到特朗普,无缝切换生成历届美国总统
- 深入理解MySQL中事务隔离级别的实现原理
- 浅析常见的算法范式
- 检查 JavaScript 变量是否为数字的几种方式
- 玩转Google Colab!附20种小技巧
- 猿实战19——商品发布之商详数据准备
- 【大家的项目】code-minimap
- 尤大 几天前发在 GitHub 上的 vue-lit 是啥?
- 用回溯算法求解数独问题
- bug 回忆录(四)