基础动态规划题目合集
- 1.abc291_d
- 2.abc291_f
- 3.牛客2023寒假集训营1 - M
- 4.cf 1741 E Sending a Sequence Over the Network
- 5.abc262_d
- 6.abc 298 e Unfair Sugoroku
- 7.abc 300 E Dice Product 3
- 8.abc 306 D Poisonous Full-Course
- 9.abc 270 D Stones
- 10.abc 312 D - Count Bracket Sequences
- 11.cf 903 div.3 E. Block Sequence
- 12.leetcode 546. 移除盒子
- 13.洛谷 P3842 [TJOI2007] 线段
1.abc291_d
水题,简单规划即可(自己的做法可见提交代码)
2.abc291_f
需要用到一点点思维和动态规划
官方解析:abc291_f_solution
3.牛客2023寒假集训营1 - M
\(dp[i][j]\)表示将小波奇的m个仙贝已经分给i个人,共分出了j个仙贝时的最大好感度之和
4.cf 1741 E Sending a Sequence Over the Network
dp[i]表示到第i个位置,可以行程想要的a数组
之后遍历b数组,假设遇到的一个数可以作为左边界或者右边界,同时保证前面无缝接上前面已经可以实现a数组的部分,利用dp即可
5.abc262_d
此题仍待理解!=!
动态规划
i:1~n dp[j][k][l]代表前j个元素挑选k个元素,且这k个元素取余i的和为l
(不知理解是否还存在问题)
详见提交代码和题解
6.abc 298 e Unfair Sugoroku
阿巴阿巴。。。说实话,自己做的话都没有发现可以运用动态规划来求解。。。
首先可以明白,Ta和Ao的位置大的部分影响T和A位置小的部分,而且位置小的部分由位置大的地方来决定,故可以使用动态规划来求解。
定义dp[i][j][f]
为Ta在i位置,Ao在j位置时,Ta赢得概率(f=0意味着下一步由Ta走;f=1意味着下一步由Ao走)。
那么规划的初始条件就是
dp[i][n][f]=0;//Ao到了
dp[n][i][f]=1;//Ta到了
递推式也易知
之后遍历整个范围,最终的答案为dp[a][b][0]
具体代码见提交记录
7.abc 300 E Dice Product 3
动态规划,细节看官方题解,这里仅罗列结论
我们定义dp(n)表示从n开始到达题目所给的N的概率
那么,有\(dp(n)=\frac{dp(n)+dp(2n)+dp(3n)+dp(4n)+dp(5n)+dp(6n)}{6}\)
即\(dp(n)=\frac{dp(2n)+dp(3n)+dp(4n)+dp(5n)+dp(6n)}{5}\);
而且当n>N时,dp(n)=0;dp(N)=1;
所以可以通过动态规划来求解,最终答案为dp(1)
8.abc 306 D Poisonous Full-Course
dp[course i][Takahashi’s state j]
The maximum total tastiness of the courses that he has eaten when he has decided whether to eat or skip for the first i courses and his state is j ( 0 … he has an healthy stomach, 1 … he has an upset stomach.)
递推过程:
// Note that 0-based indices are used for the courses in the sample code
// Initialize the DP table
for(long long i=0;i<=n;i++){
dp[i][0]=-4e18; // dp[i][0] = -∞
dp[i][1]=-4e18; // dp[i][1] = -∞
}
dp[0][0]=0; // Initially, he has a healthy stomach
for(long long i=0;i<n;i++){
// Transition for his choice of eating the i-th course
if(x[i]==0){
dp[i+1][0]=max(dp[i][0],max(dp[i][0],dp[i][1])+y[i]);
}
else{
dp[i+1][1]=max(dp[i][1],dp[i][0]+y[i]);
}
// Transition for his choice of skipping the i-th course
dp[i+1][0]=max(dp[i+1][0],dp[i][0]);
dp[i+1][1]=max(dp[i+1][1],dp[i][1]);
}
详可见代码
9.abc 270 D Stones
题意
给 n 个石头和一个 A 序列(个数为 k ),Takahashi and Aoki 轮流从石头堆中选取不超过当前石头数的且在 A 序列里的个数的石头并移除它。两个人都想自己移去的石头数目尽可能大,问你先手 Takahashi 能移除多少个石头?
思路
首先考虑贪心,会发现其实没法考虑完全!
考虑用动态规划求解这种复杂策略问题
状态:
定义 \(dp[i]\) 表示先手在面对 i 个的石头的局面可以取得的最大石子数】
初始 \(dp[a[i]] = a[i]\)
转移:
当 \(a[j] \le i\) 时,当前先手可以执行 \(a[j]\) 操作,让后手面对 \(i - a[j]\)局面,那么当前先手能取到的石子数最大值即为$i - dp[i - a[j]] $,所以遍历 \(i\) 下可能的 \(a[j]\),那么$dp[i] = max(dp[i], i - dp[i - a[j]]) $
从前往后遍历取大,最终答案即为 \(dp[n]\)
10.abc 312 D - Count Bracket Sequences
满足题意的字符串一定是任意前缀左括号数大于等于右括号数,整体左括号数等于右括号数
可以利用 DP 求解
状态
\(dp[i][j]\) 表示字符串第 i 个字符处,j 为前 i 个字符中左括号减右括号的个数,值即为方案数
转移
三个转移
- $ss[i] = ( $,那么 $dp[i][j] -> dp[i + 1][j + 1] $
- $ss[i] = ) $,那么 $dp[i][j] -> dp[i + 1][j - 1] $
- $ss[i] = ? $,那么 $dp[i][j] -> dp[i + 1][j + 1] $ 且 $dp[i][j] -> dp[i + 1][j - 1] $
最终答案即为 $dp[n][0] $
代码传送门
11.cf 903 div.3 E. Block Sequence
状态
dp[i] 表示对区间 [i, n] 所需的最小操作次数使得其 beautiful
初值 dp[n] = 1, dp[n + 1] = 0
转移
- dp[i] = dp[i + 1] + 1,移除当前第 i 个字符,延续成立
- 考虑 i + a[i] + 1 的位置,其小于等于 n + 1 则传递 dp[i + a[i] + 1],不然a[i]就无法利用
两种转移取小即可
12.leetcode 546. 移除盒子
状态
\(dp[l][r][k]\) 表示移除区间 \([l, r]\) 和后面 \(k\) 个 \(a_r\) 时所能得到的最大积分
转移
13.洛谷 P3842 [TJOI2007] 线段
状态
\(dp[i][0]\) 表示移动到第 i 行左端点所需的最短路程
\(dp[i][1]\) 表示移动到第 i 行右端点所需的最短路程
转移
初值:\(dp[1][0] = r[1] - 1 + r[1] - l[1] ; dp[1][1] = r[1] - 1 ;\)