您的位置:首页 > 其它

简单dp总结与习题

2016-07-19 08:34 375 查看
一、一般思路:

1、原问题分解为子问题

2、确定状态

3、确定一些初始状态(边界)的值

4、确定状态转移方程。

二、问题特点:

1、问题有最优子结构

2、无后效性

三、求解形式:

1、记忆递归型

2、我为人人递推型(更新原有节点的值)(要注意递推顺序)

3、人人为我递推型(用已有的求未知的)

四、优化方式

1、时间优化:记忆化

2、空间优化:滚动数组

五、设计状态技巧:

如果一个状态不够用就多加几个状态变量,细化状态

POJ - 1163 The Triangle

一、递归型写法(注意记忆化):

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <vector>

using namespace std;
const int maxn = 105;
int Maxsum[maxn][maxn], a[maxn][maxn], n;

int maxsum(int r, int c)
{
if (Maxsum[r][c] != -1) {
return Maxsum[r][c];
}
if (r == n) {
Maxsum[r][c] = a[r][c];
} else {
Maxsum[r][c] = max (maxsum (r + 1, c), maxsum (r + 1, c + 1)) + a[r][c];
}
return Maxsum[r][c];
}

int main()
{
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <=i; j++) {
scanf ("%d", &a[i][j]);
}
}
memset (Maxsum, -1, sizeof(Maxsum));
maxsum (1, 1);
printf ("%d\n", Maxsum[1][1]);
return 0;
}


二、人人为我递推型写法

1、无空间优化:

const int maxn = 105;
int  a[maxn][maxn], Maxsum[maxn][maxn], n;

int main()
{
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <=i; j++) {
scanf ("%d", &a[i][j]);
}
}
for (int i = 1; i <= n; i++) {
Maxsum
[i] = a
[i];
}
for (int i = n - 1; i >= 1; i--) {//递归顺序:由下到上
for (int j = 1; j <= i; j++) {
Maxsum[i][j] = max (Maxsum[i + 1][j], Maxsum[i + 1][j + 1]) + a[i][j];
}
}
printf ("%d\n", Maxsum[1][1]);
}


2、滚动数组空间优化:

const int maxn = 105;
int  a[maxn][maxn], Maxsum[maxn], n;

int main()
{
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <=i; j++) {
scanf ("%d", &a[i][j]);
}
}
for (int i = 1; i <= n; i++) {
Maxsum[i] = a
[i];
}
for (int i = n - 1; i &
a3e3
gt;= 1; i--) {//递归顺序:由下到上
for (int j = 1; j <= i; j++) {
Maxsum[j] = max (Maxsum[j], Maxsum[j + 1]) + a[i][j];
}
}
printf ("%d\n", Maxsum[1]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: