CodeForces 1195C Basketball Exercise
- 题意:有两排小哥哥,每排都有 n n n个小哥哥。我们要从这 2 n 2n 2n个小哥哥里选择任意个,使得这些小哥哥的身高总和最大(花痴脸). 限制我们选择的小哥哥不能是一排中相邻的两个。
- 思路:定义 d p [ ] [ 3 ] dp[ \ ][3] dp[ ][3]其中 d p [ p o s ] [ 0 ] dp[pos][0] dp[pos][0]表示 p o s pos pos位置上不选人, d p [ p o s ] [ 1 ] dp[pos][1] dp[pos][1]表示选择 p o s pos pos位置上第一排的小哥哥, d p [ p o s ] [ 2 ] dp[pos][2] dp[pos][2]表示选择 p o s pos pos位置上第二排的小哥哥。
- 很容易得到 d p dp dp方程如下:
- d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 2 ] ) ; dp[i][0]=max(dp[i-1][0],dp[i-1][1],dp[i-1][2]); dp[i][0]=max(dp[i−1][0],dp[i−1][1],dp[i−1][2]); //这个位置不选,那么上个位置不选或选谁都无所谓
- d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 2 ] ) + h [ 0 ] [ i ] ; dp[i][1]=max(dp[i-1][0],dp[i-1][2])+h[0][i]; dp[i][1]=max(dp[i−1][0],dp[i−1][2])+h[0][i]; //第 i i i位选第一排的,那么第 i − 1 i-1 i−1位上一定不能选第一排的
- d p [ i ] [ 2 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] ) + h [ 1 ] [ i ] ; dp[i][2]=max(dp[i-1][0],dp[i-1][1])+h[1][i]; dp[i][2]=max(dp[i−1][0],dp[i−1][1])+h[1][i]; //第 i i i位选第二排的,那么第 i − 1 i-1 i−1位上一定不能选第二排的
CodeForces 1207C Gas Pipeline
- 题意:来,我们铺管道,立柱子!一个单位的管道需要花费 a a a,一个单位的柱子需要花费 b b b. 但是呢,不是所有时候都天时地利人和的,所以如果遇到路口,那么就要必须要架高管道。给出一个 01 01 01串,如果对应位上是 1 1 1说明必须将管道架高到高度2. 问最小花费是多少呢?【建议结合第二个样例理解题意】
- 思路:必要的花费是
m
u
s
t
=
a
∗
n
+
b
∗
(
n
+
1
)
must=a*n+b*(n+1)
must=a∗n+b∗(n+1),这个毋庸置疑。我们可以调整的是:在0的地方我们是选择继续在高度为2的地方继续铺管道,还是选择下降到高度为1的地方铺管道呢?
– 如果是 00 00 00那么我们可以上升,消耗是 a + b a+b a+b,因为既需要管道也需要柱子;也可以保持高度1,消耗为0
– 如果是 01 01 01那么我们就必须上升,消耗是 a + b a+b a+b
– 如果是 10 10 10那么我们可以下降,消耗是 a a a,也可以保持高度 2 2 2,消耗是 b b b
– 如果是 11 11 11那么我们必须保持高度2,消耗是 b b b - 由此我们可以很容易想到定义 d p [ p o s ] [ 2 ] dp[pos][2] dp[pos][2],其中 d p [ p o s ] [ 0 ] dp[pos][0] dp[pos][0]是操作 p o s pos pos位的管道在高度1, d p [ p o s ] [ 1 ] dp[pos][1] dp[pos][1]是操作 p o s pos pos位的管道在高度2. 那么:
- 如果
p
o
s
pos
pos位是
1
1
1 //那该位置不可能为0
– d p [ p o s ] [ 0 ] = I N F ; dp[pos][0]=INF; dp[pos][0]=INF;
– d p [ p o s ] [ 1 ] = m i n ( d p [ p o s − 1 ] [ 0 ] + a + b , d p [ p o s − 1 ] [ 1 ] + b ) ; dp[pos][1]=min(dp[pos-1][0]+a+b, dp[pos-1][1]+b); dp[pos][1]=min(dp[pos−1][0]+a+b,dp[pos−1][1]+b); - 如果
p
o
s
pos
pos位是
0
0
0
– d p [ p o s ] [ 0 ] = m i n ( d p [ p o s − 1 ] [ 1 ] + a + b , d p [ p o s − 1 ] [ 0 ] ) ; dp[pos][0]=min(dp[pos-1][1]+a+b, dp[pos-1][0]); dp[pos][0]=min(dp[pos−1][1]+a+b,dp[pos−1][0]);
– d p [ p o s ] [ 1 ] = m i n ( d p [ p o s − 1 ] [ 0 ] + a + b , d p [ p o s − 1 ] [ 1 ] + b ) ; dp[pos][1]=min(dp[pos-1][0]+a+b, dp[pos-1][1]+b); dp[pos][1]=min(dp[pos−1][0]+a+b,dp[pos−1][1]+b);
CodeForces 1312E Array Shrinking
- 题意:相邻的两个相等的数x可以合并为x+1,问可以通过合并操作得到的数列最小长度?
- 思路:我们定义 d p [ r ] dp[r] dp[r]表示区间 [ 1 , n ] [1,n] [1,n]可缩并得到的最小长度。对于右端点 r r r,我们可以从右端点开始枚举左端点 l l l,看区间 [ l , r ] [l,r] [l,r]是不是可以被合并为长度1. 如果可以显然 d p [ r ] = d p [ l − 1 ] + 1 dp[r]=dp[l-1]+1 dp[r]=dp[l−1]+1.
那么我们如何判断一个区间是不是可以被合并呢?
这个思路的重点是什么?是从右端点开始枚举左端点 .
我们定义now为枚举到的左端点 a [ l ] a[l] a[l],并且定义一个栈,栈中的内容是我们枚举到的区间 [ l , r ] [l, r] [l,r]缩并完之后的剩下的值。那么对于当前枚举到的 l l l来说,是不是栈中的元素是区间 [ l + 1 , r ] [l+1,r] [l+1,r]缩并后的?
显然,如果now等于栈顶元素,那么就踢掉栈顶(合并栈顶元素和now),now自增1. 直到now不能合并为止(包括两种情况:栈空 或者 now ≠ \neq = 栈顶元素)
这个写法,大家可以自行考虑~hhh,窝觉得超级妙欸
CodeForces 1221D Make The Fence Great Again
- 题意:有 n n n个木板,我们必须要使得相邻两个木板的高度不同。增高木板不限次,问最小花费?
- 思路:我们可以发现,每块木板的高度增加一定不会超过两次。(可以自己举例验证)所以我们我们可以选择定义数组 d p [ p o s ] [ 3 ] dp[pos][3] dp[pos][3](0\1\2分别表示保持原高度,高度增加1,高度增加2)表示截止到位置 p o s pos pos,并且位置 p o s pos pos的木板增加高度0\1\2的最小花费。
- 我们遍历一遍所有的木板
- 如果 p o s pos pos位置上的木板和前面的木板高度相同,那么 d p [ p o s ] [ h ] = m i n ( d p [ p o s − 1 ] [ a d d ] + a d d ∗ c o s t [ i ] ) , 其 中 a d d ≠ h dp[pos][h]=min(dp[pos-1][add]+add*cost[i]),其中add \neq h dp[pos][h]=min(dp[pos−1][add]+add∗cost[i]),其中add=h.
- 如果不相同,那么首先 d p [ p o s ] [ a d d ] = d p [ p o s − 1 ] [ a d d ] + a d d ∗ c o s t [ i ] dp[pos][add]=dp[pos-1][add]+add*cost[i] dp[pos][add]=dp[pos−1][add]+add∗cost[i],然后判断当前木板可行的其他两个高度是不是和前一个木板相同。
-
举个栗子
首先继承: d p [ p o s ] [ 2 ] = d p [ p o s − 1 ] [ 2 ] + 2 ∗ c o s t [ p o s ] dp[pos][2]=dp[pos-1][2]+2*cost[pos] dp[pos][2]=dp[pos−1][2]+2∗cost[pos],然后判断其他两个高度 h e i g h t [ p o s − 1 ] height[pos-1] height[pos−1]和 h e i g h t [ p o s − 1 ] + 1 和 h e i g h t [ p o s ] + 2 height[pos-1]+1和height[pos]+2 height[pos−1]+1和height[pos]+2是不是相同,如果不相同,那么更新 d p [ p o s ] [ 2 ] dp[pos][2] dp[pos][2]为可能的最小值【注意要用 d p [ p o s − 1 ] [ ] + 2 ∗ c o s t [ p o s ] dp[pos-1][ \ ]+2*cost[pos] dp[pos−1][ ]+2∗cost[pos]再和 d p [ p o s ] [ 2 ] dp[pos][2] dp[pos][2]比较】。 d p [ p o s ] [ 0 ] dp[pos][0] dp[pos][0]和 d p [ p o s ] [ 1 ] dp[pos][1] dp[pos][1]类似。