如果全部掌握了DP应该算是小有所成了
一半是寒假写的,另一半算是暑假补作业。
A - Frog 1
B - Frog 2
C - Vacation
D - Knapsack 1
E - Knapsack 2
F - LCS
G - Longest Path
H - Grid 1
I - Coins
J - Sushi
1 | int cnt[10], a, n; |
K - Stones
1 | int n, k, a[200], dp[N][2], p; |
L - Deque
1 | int n, a[N]; |
M - Candies
1 | int n, k, a[N]; |
N - Slimes 石子合并问题
1 | ll dp[N][N]; |
O - Matching 状压dp
1 | int n, mp[N][N]; |
P - Independent Set 树形dp
思路
树形dp的思想就是从下向上的dp,
1 | int n, tot, head[N], ver[N<<2], nex[N<<2]; |
Q - Flowers LIS思想 + 线段树维护
题意
每支花有高度值和价值两个整数,要求从1~n选出一段,使得高度呈单调递增,同时价值的总和最大。求最大价值。
思路
根据最长上升子序列的思想很容易想到O(n^2)的做法,但是会T。我们发现对于每一支花,他的dp价值就等于前面比他低的最高的花的dp值与其相加。使用线段树进行维护。
1 |
|
R - Walk 倍增floyd???
题意
一个有向图,起点和终点任意问有多少种长度为k的不同路线;
思路
矩阵快速幂
1 | ll n, k; |
S - Digit Sum 数位dp
题意
数位dp的入门题目,给出范围1~r,求出各位相加的和模一个数为0的数有多少个。
思路
基于“试填”的思想从高位到低位递归。
1 | ll dp[N][M][2]; |
T - Permutation 求出递推公式
题意
给出一个全排列数组的长度和相邻数之间的关系,求满足条件的数组有多少个。
思路
设dp[i][j]表示1~i之间的全排列中第i位上的数字是j的情况有多少种。
- 当第i个关系为 < 时,有dp[i][1]=0; dp[i][2]=dp[i-1][1]+dp[i]1; dp[i][3]=dp[i-1][2]+dp[i][2];……
- 当第i个关系为 < 时,有dp[i][i]=0; dp[i][i-1]=dp[i][i]+dp[i-1][i-1];……
1 | ll dp[N][N], n, ans; |
U - Grouping 状压DP枚举子集
枚举子集的公式推导
题意
给出n个兔子,任意分组,得分为分到一组的匹配贡献值的和,求最大的得分;
思路
根据给出的数据量最多16个兔子,刚好适合利用状压dp枚举1 ~ (1 << n)的状态,并且枚举子集获取状态i的情况下的最大得分。
1 | int n, a[N][N], con[N]; |
V - Subtree
W - Intervals \
题意
给出一个长度为N的字符串容器,每个位置只能填0/1。接下来是M个条件,在li~ri之间如果存在1,那么就获得ai分(若第i个位置为1,那么得到包括该点所有区间的分数)。求可以获得的最大分数。
思路
按照右端点进行排序,可以遍历覆盖该点的所有区间。tag[i]表示该点为1时的得分和,sum[i]表示该点为1时的最大值。使用线段树进行转移。
转移过程:
- 维护之前使用根节点(当前最大分值)对当前点进行维护。
- 将相同右端点的区间统一维护;
1 | int n, m; |
X - Tower 转化为背包问题
题意
堆石头,每块石头有各自的重量,承载能力,价值。求可以堆出来的最大价值。
思路
从上往下堆更加容易,但是要提前排好序。可以发现当需要选择接下来堆两块石头i和j的顺序时,可以贪心的思考。比如i在j上面,当前的重量是w,那么si < w + wj, sj > w + wi。联立两个式子可以得到si + wi < sj + wj。排序后问题转化为01背包。
1 | struct node { |