下面包含最近做过的比较有价值的动态规划的题目以及简要题解,并附上了有注释,较为易懂的AC代码。
UVaOJ(紫书习题)
1. UVA10163:题目要求最小值的最大,这启发我们二分答案。之后还要求求出花费的最小值,这就相当于01背包了,状态及状态转移方程:我的代码
// dp[cur][cnt]: mininum cost when dealing with p[cur] and already cnt storages safe
// dp[cur][cnt] = min dp[cur+1][cnt], dp[cur+1][cnt+p[cur]/l] + p[cur] (if possible)
// Corner: dp[m+1]: if cnt < n then inf else 0;
// Goal: dp[1][0]
2. UVA1631:多阶段决策。每个状态保存已经让1~cur-1归位,现在正在考虑第cur位,并且目前cur处和cur+1位的数分别是num_cur与num_cur+1,状态转移方程是:我的代码
dp[i][j][k] = min(dp[i][j][k], dp[i+1][j+ch2][k+ch3])
3. UVA12589 Learning Vector:多阶段决策问题。首先一个重要的观察是应当对向量按斜率排序,这样可以做到无后效性。由此我们用保存考虑到第cur个向量时y轴坐标,状态转移方程:我的代码
dp[i][j] = max dp[pos+y[k]][cur+1]+(2*ypos+y[k])*x[k]
4. Chopsticks UVA - 10271 :多阶段决策问题。重要观察是选的那两根短筷子一定要长度相邻,这样就变成01背包了。保存状态。注意检查每一状态是否可以选出长筷子(我最后用的是
与开头注释不一样),注意本题记忆化搜索很慢,1890 ms!状态转移方程见下方,我的代码
dp[cur][cnt] = min(dp[cur+1][cnt], dp[cur+2][cnt+1]+val[cur] if ok)
Codeforces
1. Educational 49 E. Inverse Coloring:首先要明确画出第一行和第一列之后,方案就已经确定了。那么最大矩形也就是第一行中最长连续同色子序列与第一列中的乘积,这两者实际可以用一次dp求出,但是最后不要忘记答案除以二,因为第一行第一列的方格被考虑了两次。另外这种方法是O(n^3)的,可能会爆内存,这里采用了滚动数组。我的代码
2. Educational Codeforces Round 50 (Rated for Div. 2), problem: (C) Classy Numbers
这可以使用数位dp来完成。从最高位向个位依次填数字,如果存在某一位已经小于原数了,就用公式O(1)计算;否则根据这一位是否是1进行dp。我的代码
区间dp,dp[l][r][0/1]含义具体见代码:(这道n^3复杂度的题n<=700,但记忆化搜索跑得飞快,才61ms)我的代码