区间 DP 专场:愉快爆炸

T1

题目大意

有 \(n\) 个有颜色的块,连续 \(k\) 个相同颜色的就可以消掉

现在可以在任意位置插入任意颜色的方块,问最少插入多少个可以全部抵消

题解

先把连续的化成一块,问题变为如何消掉一块。 \(num\) 为个数, \(color\) 为颜色

设 \(F_{i,j,len}\) 表示表示 \([i,j]\) 后面有 \(len\) 个和 \(j\) 颜色一样的与 \(j\) 一起消除。

初始 \(F_{i,i,len}=\max(0,k-num_i-len)\)

然后 \(F_{i,j,len}=F_{i,j-1,0}+\max(0,k-num_j-len)\) 即单独消去

枚举中转点 \(k'\) ,\(F_{i,j,len}=\min_{k'=i}^{j-1}F_{i,k',\min(k,len+num_j)}+F_{k+1,j-1,0} (color_j=color_{k'})\)

就是先消掉 \([k+1,j-1]\) 然后再将第 \(j\) 块与 \(i,k\) 一起操作

目标: \(F_{1,n,0}\)

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,K,x[N],cl[N],w[N],tot;
int f[N][N][10];
int main() {
scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++)scanf("%d",&x[i]);
cl[1]=x[1],w[1]=tot=1;
for(int i=2;i<=n;i++) {
if(x[i]^x[i-1]) {
++tot,cl[tot]=x[i],w[tot]=1;
} else ++w[tot];
}
memset(f,100,sizeof(f));
n=tot;
for(int i=1;i<=n;i++)
for(int l=0;l<=K;l++)
f[i][i][l]=max(0,K-w[i]-l);
for(int l=2;l<=n;l++)
for(int i=1,j=l;j<=n;i++,j++)
for(int le=0;le<=K;le++) {
f[i][j][le]=f[i][j-1][0]+max(0,K-w[j]-le);
for(int k=i;k<j;k++)
if(cl[j]==cl[k])
f[i][j][le]=min(f[i][j][le],f[i][k][min(le+w[j],K)]+f[k+1][j-1][0]);
}
printf("%d",f[1][n][0]);
return 0;
}

总结

这道题想到了 \(\text{dp}\) 却没有想到区间,更没有想到多设 \([len]\) 这一维

下次要学会通过多一个状态处理转移的错误

T2

题目大意

给你 \(n\) 个 \(a_i\times b_i\) 的矩阵,问乘在一起最少要多少次乘法

输入确保能够相乘

题解

因为输入确保能够相乘,其实就是一个区间 \(\text{dp}\)

枚举中转点 \(k\) 时,这个区间 \([i,j]\) 的贡献是 \(x_i\cdot y_k\cdot y_j\)

#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,x[N],y[N],f[N][N];
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
for(int l=2;l<=n;l++)
for(int i=1,j=l;j<=n;i++,j++) {
f[i][j]=2100000000;
for(int k=i;k<=j;k++)
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+x[i]*y[k]*y[j]);
}
printf("%d",f[1][n]);
}

总结

这题以为是贪心,因为没有认真想提示的含义

T3

题目大意

给你一圈数,取一个数的贡献是这个数和其左边、右边的数的积

最后拿完只有两个数,问最大得分和最小得分的差

题解

  1. 断环成列
  2. 枚举区间 \([i,j]\) 中的最后取得数 \(k\in[i,j)\) 那么贡献为 \(a_i\cdot a_{k+1}\cdot a_{j+1}\)
#include<bits/stdc++.h>
using namespace std;
const int N=205;
int n,x[N],f[N][N],g[N][N];
int mx,mn=2100000000;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&x[i]),x[i+n]=x[i];
for(int l=2;l<=n;l++) {
for(int i=1,j=l;j<=(n<<1);i++,j++) {
f[i][j]=2100000000;
for(int k=i;k<j;k++) {
g[i][j]=max(g[i][j],g[i][k]+g[k+1][j]+x[i]*x[k+1]*x[j+1]);
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+x[i]*x[k+1]*x[j+1]);
}
}
}
for(int i=1;i<=n;i++)
mx=max(mx,g[i][i+n-2]),
mn=min(mn,f[i][i+n-2]);
printf("%d",mx-mn);
}

总结

这题不知道如何计算贡献,多想想状态的含义

T4

题目大意

\(n\) 个整数组成的圆环,\(i,j\) 的距离为两个格子之间的格子数的最小值

有一个开始指向 1 的指针,取一个数的代价即这个数的值

开始可取下指针所指的那个数以及与这个格子距离小于 \(k\) 的数

可以转动,每次转由一个格子转向其相邻的格子,且代价为圆环上还剩下的数的最大值

题解

所有各自都是要取得,至少需要 \(\sum_{i=1}^n a_i\)

开始可以取走距离小于 \(k\) 的,就是 \([1,k+1],[k,n]\) 全都没了

问题变成一个取完所有数的最小花费,用区间 \(DP\)

设 \(f_{i,j}\) 为从 \(i\) 取到 \(j\) 的最小话费,所以 \(f_{i,j}\ne f_{j,i}\)

区间最大可以预处理为 \(mx_{i,j}\)

\(f_{i,j}=\min(f_{i+1,j}+mx_{i,j},f_{j-1,i}+(len[1,i]+len[j,n])*mx_{i,j})\)

\(f_{i,j}=\min(f_{i-1,j}+mx_{i,j},f_{j+1,i}+(len[1,j]+len[i,n])*mx_{i,j})\)

就是一种正来一种反来

#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int n,K,ans,x[N],f[N][N],mx[N][N];
int main() {
scanf("%d%d",&n,&K);
memset(f,100,sizeof(f));
for(int i=1;i<=n;i++) {
scanf("%d",&x[i]);
ans+=x[i];
mx[i][i]=f[i][i]=x[i];
}
if(n<=K+K+1)return printf("%d",ans),0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
mx[i][j]=mx[j][i]=max(mx[i][j-1],x[j]);
for(int l=1;l<n-K-K;l++) {
for(int i=K+2,j=i+l;j<=n-K;i++,j++)
f[i][j]=min(f[i+1][j]+mx[i][j],f[j-1][i]+(i-K-1 + n-K-j)*mx[i][j]);
for(int i=n-K,j=i-l;j>=K+2;i--,j--)
f[i][j]=min(f[i-1][j]+mx[i][j],f[j+1][i]+(j-K-1 + n-K-i)*mx[i][j]);
}
ans+=min(f[n-K][K+2],f[K+2][n-K]);
printf("%d",ans);
}

总结

这道题确实是比较好,要学会转换问题

End

这次区间 \(dp\) 给本蒟蒻敲响警钟,要注意了

2021.03.20【NOIP提高B组】模拟 总结的更多相关文章

  1. 5820. 【NOIP提高A组模拟2018.8.16】 非法输入(模拟,字符串)

    5820. [NOIP提高A组模拟2018.8.16] 非法输入 (File IO): input:aplusb.in output:aplusb.out Time Limits: 1000 ms   ...

  2. JZOJ 5818. 【NOIP提高A组模拟2018.8.15】 做运动

    5818. [NOIP提高A组模拟2018.8.15] 做运动 (File IO): input:running.in output:running.out Time Limits: 2000 ms  ...

  3. JZOJ 5812. 【NOIP提高A组模拟2018.8.14】 区间

    5812. [NOIP提高A组模拟2018.8.14] 区间 (File IO): input:range.in output:range.out Time Limits: 1000 ms  Memo ...

  4. 2021.04.03【NOIP提高B组】模拟 总结

    T1 题目大意:求最小的 \(n\in[0,lim]\) 使得区间 \([L,R]\) 在线段树建树 \(build(0,n)\) 的区间内 考场时想到了正解,结果推式子退错了... 其实就是从下往上 ...

  5. 2021.05.03【NOIP提高B组】模拟 总结

    比较水的一场比赛,却不能 AK T1 有 \(n\) 次,每次给 \(A_i,B_i\) 问以 \(i\) 结尾的 \(A,B\) 的匹配中最大和的最小值 问最大和的最小值,却不用二分. 如果暴力排序 ...

  6. [JZOJ5817] 【NOIP提高A组模拟2018.8.15】 抄代码

    Description J 君是机房的红太阳,每次模拟她总是 AK 虐场.然而在 NOIP2117 中,居然出现了另一位 AK 的选手 C 君! 这引起了组委会的怀疑,组委会认为 C 君有抄袭 J 君 ...

  7. [jzoj 5782]【NOIP提高A组模拟2018.8.8】 城市猎人 (并查集按秩合并+复杂度分析)

    传送门 Description 有n个城市,标号为1到n,修建道路花费m天,第i天时,若gcd(a,b)=m-i+1,则标号为a的城市和标号为b的城市会建好一条直接相连的道路,有多次询问,每次询问某两 ...

  8. [jzoj 5778]【NOIP提高A组模拟2018.8.8】没有硝烟的战争 (博弈论+dp)

    传送门 Description 被污染的灰灰草原上有羊和狼.有N只动物围成一圈,每只动物是羊或狼. 该游戏从其中的一只动物开始,报出[1,K]区间的整数,若上一只动物报出的数是x,下一只动物可以报[x ...

  9. [JZOJ5818] 【NOIP提高A组模拟2018.8.15】 做运动

    Description 一天,Y 君在测量体重的时候惊讶的发现,由于常年坐在电脑前认真学习,她的体重有了突 飞猛进的增长. 幸好 Y 君现在退役了,她有大量的时间来做运动,她决定每天从教学楼跑到食堂来 ...

  10. 【NOIP提高A组模拟2018.8.14】 区间

    区间加:差分数组修改 O(n)扫描,负数位置单调不减 #include<iostream> #include<cstring> #include<cstdio> # ...

随机推荐

  1. String和int、long、double等基本数据类型的转换

    学习目标: 掌握Java的基本数据类型与String的转换 学习内容: 1.转化规则 String 转 基本数据类型 基本数据类型 变量 = 包装类.Parse基本数据类型(String); // c ...

  2. EMS邮箱数据库常用命令(一)

    案例任务:创建名为"book"的邮箱数据库,数据库文件和日志文件存储位置为"c:\book". 键入以下命令. New-MailboxDatabase -Nam ...

  3. 线程的概念及Thread模块的使用

    线程 一.什么是线程? 我们可以把进程理解成一个资源空间,真正被CPU执行的就是进程里的线程. 一个进程中最少会有一条线程,同一进程下的每个线程之间资源是共享的. 二.开设线程的两种方式 开设进程需要 ...

  4. 携程apollo配置中心服务端如何感知配置更新?

    引言 前面有写过一篇<分布式配置中心apollo是如何实时感知配置被修改>,也就是客户端client是如何知道配置被修改了,有不少读者私信我你既然说了client端是如何感知的,那服务端又 ...

  5. Java学习day41

    在力扣刷了几个算法题,对比了自己和优解的差距

  6. Python 一网打尽<排序算法>之从希尔排序算法的分治哲学开始

    1. 前言 本文将介绍希尔排序.归并排序.基数排序(桶排序).堆排序. 在所有的排序算法中,冒泡.插入.选择属于相类似的排序算法,这类算法的共同点:通过不停地比较,再使用交换逻辑重新确定数据的位置. ...

  7. Windows下搭建redis 哨兵环境

    从 https://github.com/tporadowski/redis/releases 下载windows版的redis,自行下载解压. 关于哨兵模式的讲解,强烈推荐 [深入学习redis(4 ...

  8. 解析数仓OLAP函数:ROLLUP、CUBE、GROUPING SETS

    摘要:GaussDB(DWS) ROLLUP,CUBE,GROUPING SETS等OLAP函数的原理解析. 本文分享自华为云社区<GaussDB(DWS) OLAP函数浅析>,作者: D ...

  9. FreeRTOS --(17)任务通知浅析

    转载自https://blog.csdn.net/zhoutaopower/article/details/107467305 在 FreeRTOS 中,还有一个东西也可以用作任务与任务,中断与任务的 ...

  10. WIN10 使用POWERSHELL 设置单应用KIOSK模式(win10家庭版或企业版)

    win10 使用PowerShell 设置单应用kiosk模式 win10 家版或企业版PowerShellshell 启动器 v1Autologon.exe 注意事项 win10 家庭版或企业版. ...