Luogu P3558 [POI2013]BAJ-Bytecomputer(线性dp)
P3558 [POI2013]BAJ-Bytecomputer
题意
给一个只包含\(-1,0,1\)的数列,每次操作可以让a[i]+=a[i-1],求最少操作次数使得序列单调不降。若无解则输出BRAK。
思路
毒瘤出题人alecli!你又找紫题。 --Mercury
- 结论:最优解中变换之后的数列中的数字只有\(-1,0,1\)。
- 首先考虑为什么不会出现\(2\)。\(2\)的由来只能是\(1+1=2\),而将当前位置上的\(1\)与前一位上的\(1\)相加既不会改变当前位相对于前一位已经单调不降的事实,同时会提高后面数字的大小要求,所以不使这一位上的\(1\)与前一位上的\(1\)相加显然更优。
- \(-2\)同理。
- 对于\(x\geq 3\),既然\(2\)都不会出现,那么\(x\)更不可能出现。
- 对于\(x\leq -3\),同理。
所以我们可以这样设计状态:设计\(f[i][3]\)表示前\(i\)位单调不下降的情况下尾数为某个数所需要的最少操作数,其中,\(f[i][0]\)表示前\(i\)位单调不下降的情况下尾数为\(-1\)所需要的最少操作数,\(f[i][1]\)表示尾数为\(0\),\(f[i][2]\)表示尾数为\(1\)。
那么从\(f[i-1]\)转移到\(f[i]\)时就可以这么写:
f[1][a[1]+1]=0;
for(int i=2;i<=n;i++)
if(a[i]==-1)//当前位上为-1
{
f[i][0]=min(f[i][0],f[i-1][0]);//上一位是-1,可以不用操作
f[i][2]=min(f[i][2],f[i-1][2]+2);//上一位是1,操作两次把-1变成1
}
else if(a[i]==0)//当前位上为0
{
f[i][0]=min(f[i][0],f[i-1][0]+1);//上一位是-1,操作两次把0变成-1
f[i][1]=min(f[i][1],f[i-1][0]);//上一位是-1,可以不用操作
f[i][1]=min(f[i][1],f[i-1][1]);//上一位是0,可以不用操作
f[i][2]=min(f[i][2],f[i-1][2]+1);//上一位是1,操作一次把0变成1
}
else if(a[i]==1)//当前位上为1
{
f[i][0]=min(f[i][0],f[i-1][0]+2);//上一位是-1,操作两次把1变成-1
f[i][1]=min(f[i][1],f[i-1][0]+1);//上一位是-1,操作一次把1变成0
f[i][2]=min(f[i][2],f[i-1][0]);//上一位是-1,可以不用操作
f[i][2]=min(f[i][2],f[i-1][1]);//上一位是-1,可以不用操作
f[i][2]=min(f[i][2],f[i-1][2]);//上一位是-1,可以不用操作
}
这样转移下去,就能得到答案了。答案在\(f[n][0],f[n][1],f[n][2]\)中选取最小值。
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,ans,a[1000005],f[1000005][3];
int read()
{
int f=1,re=0;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return f*re;
}
int main()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read();
memset(f,0x3f,sizeof f);
f[1][a[1]+1]=0;
for(int i=2;i<=n;i++)
if(a[i]==-1)
{
f[i][0]=min(f[i][0],f[i-1][0]);
f[i][2]=min(f[i][2],f[i-1][2]+2);
}
else if(a[i]==0)
{
f[i][0]=min(f[i][0],f[i-1][0]+1);
f[i][1]=min(f[i][1],f[i-1][0]);
f[i][1]=min(f[i][1],f[i-1][1]);
f[i][2]=min(f[i][2],f[i-1][2]+1);
}
else if(a[i]==1)
{
f[i][0]=min(f[i][0],f[i-1][0]+2);
f[i][1]=min(f[i][1],f[i-1][0]+1);
f[i][2]=min(f[i][2],f[i-1][0]);
f[i][2]=min(f[i][2],f[i-1][1]);
f[i][2]=min(f[i][2],f[i-1][2]);
}
ans=min(f[n][0],min(f[n][1],f[n][2]));
if(ans!=0x3f3f3f3f) printf("%d",ans);
else printf("BRAK");
///CHECK:
///for(int i=1;i<=n;i++) printf("\n%d %d %d",f[i][0],f[i][1],f[i][2]);
return 0;
}
Luogu P3558 [POI2013]BAJ-Bytecomputer(线性dp)的更多相关文章
- Luogu P1541 乌龟棋 【线性dp】
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行 N 个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第 N 格是终点,游戏要求玩家控制一个乌龟 ...
- 线性dp
线性dp应该是dp中比较简单的一类,不过也有难的.(矩乘优化递推请出门右转) 线性dp一般是用前面的状态去推后面的,也有用后面往前面推的,这时候把循环顺序倒一倒就行了.如果有的题又要从前往后推又要从后 ...
- 洛谷P1140 相似基因(线性DP)
题目背景 大家都知道,基因可以看作一个碱基对序列.它包含了444种核苷酸,简记作A,C,G,TA,C,G,TA,C,G,T.生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物. 在一个人类 ...
- 线性DP总结(studying
写在前面 虽然都说线性DP是入门,但我还是今天才开始学 线性DP就是珂以通过线性处理得出答案的一种DP 每一种状态都可以从前面推得,并且推导过程是呈线性的 参考题单(本人现在主要用luogu,所以这些 ...
- LightOJ1044 Palindrome Partitioning(区间DP+线性DP)
问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...
- Codeforces 176B (线性DP+字符串)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...
- hdu1712 线性dp
//Accepted 400 KB 109 ms //dp线性 //dp[i][j]=max(dp[i-1][k]+a[i][j-k]) //在前i门课上花j天得到的最大分数,等于max(在前i-1门 ...
- 动态规划——线性dp
我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模 ...
- POJ 2479-Maximum sum(线性dp)
Maximum sum Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33918 Accepted: 10504 Des ...
随机推荐
- python open函数关于w+ r+ 读写操作的理解(转)
r 只能读 (带r的文件必须先存在)r+ 可读可写 不会创建不存在的文件.如果直接写文件,则从顶部开始写,覆盖之前此位置的内容,如果先读后写,则会在文件最后追加内容.w+ 可读可写 如果文件存在 则覆 ...
- CSIC_716_20191113【装饰器进阶以及迭代器】
装饰器的进阶主要包含叠加装饰器和有参装饰器 叠加装饰器:在一个被装饰的对象中,添加多个装饰器. 为什么要用叠加装饰器的原因: -每一个新的功能都应该写一个新的装饰器,否则会导致,代码冗余,结构不 ...
- SUBTRACT
SUBTRACT 给出一个长度为n序列\(\{a_i\}\),定义一个操作,记做\(con(a,i)\),意思是用\(a_i-a_{i+1}\)替代\(a_i,a_{i+1}\),显然最后一个数字不能 ...
- 云HBase备份恢复,为云HBase数据安全保驾护航
摘要: 介绍了阿里云HBase自研备份恢复功能的基本背景以及基本原理架构和基本使用方法. 云HBase发布备份恢复功能,为用户数据保驾护航.对大多数公司来说数据的安全性以及可靠性是非常重要的,如何 ...
- thinkphp 自动加载
在3.2中,基本上无需手动加载类库文件,你可以很方便的完成自动加载. 命名空间自动加载 系统可以通过类的命名空间自动定位到类库文件,例如: 我们定义了一个类 Org\Util\Auth 类: name ...
- vs 利用web deploy发布 常见问题解决
1. 下载并安装 web deploy, 安装时选择自定义,选择全部安装 https://www.iis.net/downloads/microsoft/web-deploy 2. 确保iis的管理 ...
- PHP面向对象魔术方法之__call函数
l 基本介绍: (1) 当我们调了一个不可以访问的成员方法时,__call魔术方法就会被调用. (2) 不可以访问的成员方法的是指(1. 该成员方法不存在, 2. 成员方法是protected或者 p ...
- 第三周课堂笔记4thand5th
循环打印 #计算字典中的键值对的个数 print(len(a)) #获取字典中键的列表 print(a.keys()) #获取字典中值的列表 print(a.values()) #获取字典中键值对的个 ...
- FineUI使用记录
@{ ViewBag.Title = "Grid/Grid"; var F = Html.F();} @section body { @(F.Grid().IsFluid(true ...
- python语句结构(if判断语句)
一.python语句结构分类 条件控制语句:if 语句 if....elif语句 if嵌套 循环语句:while语句 for循环 控制语句:break.continue.pass语句 二.pyt ...