GDKOI2017总结

GDKOI 2017总结

SemiWaker

总述:

这次GDKOI没有达到预期的成绩。一方面是因为做题能力不够,敲代码能力太弱,导致不够时间写正解,另一方面是思考方式还需要完善,有的知识点还需要进一步的学习。这次运气因素也是有的,这告诉我既然运气不好就要做到100%有把握。

题目&&题解:

Day1:

T1:

题意:

给出一个N*N字符矩阵,字符’P’表示玩家,’1’~’9’表示炸弹。

炸弹会在其表示的数字的时间点爆炸,使得上下左右4个方向的长度L的线段范围内被炸到。

炸弹被炸到会提前爆炸。

问玩家被炸到的最早时间。

炸不到输出-1。



N<=1000,炸弹数<=3000,L<=N

题解:

直接BFS即可。

暴力模拟炸弹的爆炸,将被炸到的炸弹放入队列即可。

只需要O(N)的时间,总时间复杂度O(N*炸弹数)。

问题:

不知为什么错了一个点。(可能是-1?)

T2:

题意:

有一个密码串S,S的构造法如下:

S=01

S=0S1

S=01S

S=S01

S=S1+S2

现在密码串开头和结尾都多出了一串,密码串中可能少了一个字符,问最长的合法的密码串长度。

N<=2*10^5

题解:

由构造法得出S是一个括号匹配序列,0和1匹配。

我们用一个栈记录0的位置,把S扫一遍就可以得到0和1的匹配。

不匹配的0和1最后会分割开原串,形成类似下面的形式:

...1...1..1..1..0..0..0..0..0...

前面的1是扫描中无法匹配到0的1,后面的0是扫描完之后栈中剩下的0。

注意到他们是没有本质区别的,所以记录位置即可。



如果不能增加字符,那么求出每一个合法段的长度的最大值即可。

如果能增加字符,那么相当于把两个相邻合法段合并,求出相邻合法段总长的最大值即可。



这题有很多做法,包括DP和模拟等,可以算是杂题。

T3:

题意:

有P*Q个人,编号0~P*Q-1。任意两个人x,y的距离是min(|y-x|,P*Q-|y-x|)

如果x和y的距离是P或Q的倍数,那么x和y相邻。

要求将图划分为任意个圈,使得每一个圈人数>=3,求方案数。



P<=6 Q<=10^9

题解:

插头DP。



首先,每一个点是4连通的。

那么这个图很有可能可以画成矩阵状,实际上是可以的。

这个图的实际几何形状是“甜甜圈”状,画成平面就是矩阵,上下边界连通,左右边界连通。



考虑数据范围,P小Q超大,显然是对于P做DP,然后对于Q做矩阵乘法。



什么DP可以求划分圈方案数呢?实际上这是插头DP的例题。

一对边界变成环也是可以做的。



现在剩下两个个问题。



第一个问题:另外一边的边界也是环。



我一开始的想法是:暴力枚举第一行,然后再DP。



然而结合矩阵乘法可以得到一个简单的方法:对于转移矩阵的主对角线上的状态,表示转移到相同的状态。那么如果我们直接求转移矩阵的Q次方,主对角线上的系数和就是答案。

这是矩阵乘法优化DP的一个变形应用:直接计算转移矩阵,不管初始状态向量。



第二个问题:怎么记状态?

如果按照折线扫描线的普通记法,单行状态数会比较多。

但是我们可以回到原始的方法:一整行作为一个状态。



这种方法的问题是转移比较慢,但是放进矩阵乘法就没有区别了,都是O(n^2)。

这给我们的启示是:对于状压DP的矩阵乘法,直接一整行作为状态会比较优。



状态数有多少呢?

如果用括号匹配,是36种,但是要解码和编码。



这题有特殊性:它不在乎有多少个环。

那么每一个连通块就没有必要编号。

所以直接2^6表示每一个位置有没有插头,也是可以的。

实际状态会比括号匹配还少,不过要求实际状态的话还是要解码和编码。

因为2^18可以过,所以直接记即可。

问题及启示:

知道是插头DP,没敢编,而且细节问题也搞不定。



要写多几次插头DP,多思考细节问题。

T4:

题意:

有一个序列,每次可以从左边或者右边取一段,将他们放入一个“袜子”里。

“袜子”有两个容量V和W,要求分别满足体积不超过容量。

求最少需要多少个背包才能装下整个序列。



n<=3000

题解:

很容易得到一个简易的DP模型:

F[L][R]=min(F[L1][R1]+1) L1<=L R1>=R

使得L~L1-1和R1+1~R的总和不超过容量。



这个是一个O(n^3)的。(L1和R1关联,算一个变量。)



然后我们考虑怎么优化。

直接从方程来讲,没什么好优化的。



我们可以考虑合并状态。

把F[L][R]这个状态表示为:已经取到L和R的时候,最少的“袜子”数和已经放入的物品的总和。

这样每次我们可以考虑只取最左边和最右边。

那么转移方程变为F[L][R]=min{F[L+1][R]+0/1,F[L][R+1]+0/1)



现在的问题是:已经放入的物品的总和是一个什么样的状态?



假如只有一种容量,那么记录放入的物品的总体积就可以了。

这种状态下,两个F先比较袜子数,再比较总体积就可以确定优劣了。



但是有两种容量的话,两个体积之间无法取舍,是无法满足最优性的。



我们需要寻找另外一种记状态的方法。



比如说,记录L左边已经选了多少个。



这样显然选的越少越好。

那么右边怎么办呢?我们可以考虑二分一个位置R1,使得加上R刚好取满。



这里转移到F[L][R1] 袜子+1 左边选的长度=0



另外一种转移是左边多选一个 F[L+1][R] 再判断是否装满。



这样就变成O(n^2logn)的了。

问题和启示:

我当时用的是一个随机的方法:

考虑最原始的转移方程,L1的位置的取值。

考虑F[L][R]和F[L][R-1]的最优取
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值