动态规划题目总结(持续更新)

来源:互联网 发布:ubuntu的linux修改ip 编辑:程序博客网 时间:2024/04/28 15:32

暂且按照《训练指南》上的顺序写,每种题型对应HDU上的一道或者几道题目

数字三角形

数字三角形其实是在枚举每个阶段中的状态,此状态就是能从前一阶段已经解决的最大和问题中配合当前的状态得到的当前最大和。设 d(i, j) 表示第 i 阶段的第 j 个状态(格子)出发能得到的最大和,得到了一个状态转移方程:
d(i, j) = a(i, j) + max{ d(i + 1, j), d(i + 1, j + 1) }
自下而上的求解,因为上面的要靠下面的数据才能计算的出。
还有一个边界条件:d(n + 1, j) = 0
由于仅仅能选择左右走,所以上一阶段中的一个状态需要由下一个阶段的两个状态决定,才得到了如上的状态转移方程。
数塔》 URL: http://acm.hdu.edu.cn/showproblem.php?pid=2084
通过上面的数字三角形的分析可以很容易的写出这题的代码,如下:

        for (i = 0; i < N; ++i) {            for (j = 0; j <= i; ++j) {                cin >> a[i][j];            }        }        for (i = N - 1; i >= 0; --i) {            for (j = 0; j <= i; ++j) {                dp[i][j] = a[i][j] + max(dp[i + 1][j], dp[i + 1][j + 1]);            }        }

这个是自下而上,自左到右的一个 DP ,一定要注意DP边界,由于边界是 0,所以直接memset(dp, 0, sizeof(dp)) 就OK了。

免费馅饼》 URL: http://acm.hdu.edu.cn/showproblem.php?pid=1176
首先确定阶段和状态:显然经历的每秒是一个阶段,每个阶段中能得到的馅饼是一个状态,不过这个数字三角形的模型并没有直接给出,而是抽象成为了在第 i 秒钟落在第 j 个位置上,所以需要先将这个给出的一组数据转化成为三角形模型(起码做成一个矩阵模拟出之前的数字三角形问题)。

    for (int i = 0; i < n; ++i) {        cin >> x >> t;        dp[x][t]++;    }

代表第 x 个位置在第 t 秒的时候落下一张馅饼n (≧▽≦),于是这个数字三角形的矩阵就出来了。
再设 d(i, j) 为从 i 位置,第 j 秒出发能得到的最大馅饼数量,且这个每次只有三个选择,左中右。所以可以得到状态的转移方程如下:

d(i, j) = a(i, j) + max{ d(i - 1, j + 1), d(i, j + 1), d(i + 1, j + 1) }

有了状态转移方程可以根据状态之间的应用关系来决定是否就地更新(在同一个二维数组表示状态和状态之间的转移)或者一个二维数组表示状态另外一个表示转移。如果相邻阶段的状态可以由上一个阶段状态直接退出下一个阶段的一个状态,可用一个一位数组来优化空间,或者两个一位数组。

// 下午上课先更新到这,晚上回来继续更新,暂且发表

嵌套矩形问题

嵌套矩形是一个DAG模型,因为嵌套的关系是单向的,书中给出的解释说二元关系 可用图来建模,且如果 X 可以嵌套在 Y 里那么从 X 到 Y 连有一条有向边。反观这一DAG,求这样的嵌套最大值也就是求DAG上的最长路径。
嵌套矩形》 URL: http://acm.nyist.net/JudgeOnline/problem.php?pid=16
那么知道是求DAG上的最长路了可以设 d(i) 为从 i 点出发可到达的最远的距离,可以想象的出这样的状态转移方程:

d(i) = max{ adj(i) + 1 }
0 0
原创粉丝点击