一套dp专题训练题:http://vjudge.net/contest/view.action?cid=51495#overview
A题:
dp,然后根据每次dp的最优决策推出字符串
状态:dp[i][j]表示从i到j需要补的括号数
B题:
状态:dp[i]表示买i个物品以后的所有物品的最小花费,则dp[i]=Min(dp[j]+(sum(i,j-1)+10)*b[j-1]);j>i;不解释。。
C题:
公式变形,然后dp,最后根据公式求结果;代码有点多,细心==;用引用优化代码量
状态:dp[i][j][k][l][r]表示(j,k)到(l,r)这个矩形分i下所得到的平方和的最小值
D题:
数位dp,一般步骤为:
先dp长度为i的满足条件的数的个数,然后dfs统计;
状态:dp[i][0]表示长度为i,包含49的个数,dp[i][1]表示长度为i,不包含49的个数
dp的计算:
dp[i][0]=10*dp[i-1][0]+dp[i-2][1];
dp[i][1]=10*dp[i-1][1]-dp[i-2][1];
加法原理,保证包含所有情况且没有重复
E题:
经典的记忆化搜索,不解释==
F题:
经典问题,求最大子矩阵,思想是降维,转化为求最大子序列,o(n*n)*o(n)的时间复杂度
G题:
显然用二进制表示状态,然后递推统计即可,注意状态表示
状态:dp[i][j][k]为前i行第i行的状态为j,第i-1行的状态为k的放的总数目,枚举第i-2行的状态,可求出dp[i][j][k];
这里二维的状态表示是不可少的,一维会导致有后效性;另外要注意判断状态是否合法等等均可以预处理以节省时间
H题:
实际上是求两个序列的最长公共子序列,n最大60000多,不能直接二维dp,此题特殊在每个值都只出现一次,果断转化LIS求之
I题:
状态:dp[i][j]表示任一个玩家按最优决策在区间[i,j]里面得到的分,枚举做出的决策,得到状态转移方程:dp[i][j]=Max(sum(i,j)-dp(k,j)),k<=j+1
dp的套路:
无论哪种类型的dp,都是递推的思想,好的状态表示能轻松得出递推关系,有递推关系和初始值,进而逐步求得最终解
dp的条件,无后效性(子问题“以前”的状态与当前状态无关,所以决策的时候要考虑所有与当前状态有关的子问题),最优子结构(子问题最优是不是全局最优)