一道简单的二维动态规划题。原谅我刚学动态规划完全不理解搞了半天啊、、、后来看了别人的解题报告才恍然大悟,原来这就是动态规划啊、、、中文题意描述就不多说了。
我的解题思路:既然是求到达终点能够积累的最大幸运值,那么根据沿途的点以及移动的方式我们不难想到状态转移方程dp[i][j] = max(dp[i-1][j], dp[i][j-1], dp[i][...])。dp存储的就是到达该点能积累的最大幸运值,这有点像递推,但是动态规划和递推不同的是:递推的前置节点数量是确定的,而动态规划这是不确定的。我们从起点开始进行动态规划,直到终点,就能求得最终答案了。需要注意的是,因为幸运值可以是负值,所以初始化的dp应该是比幸运最小值还要小的。
下面是我的解题代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 23
#define M 1003
#define INF 9999999
int map[N][M];
int dp[N][M];
int n, m;
int t;
void Read(); //输入
void DataProcess(); //动态规划解题
int main()
{
scanf("%d", &t);
while (t--)
{
Read();
DataProcess();
}
return 0;
}
void Read()
{
scanf("%d %d", &n, &m);
for (int i=1; i<=n; ++i)
{
for (int j=1; j<=m; ++j)
{
scanf("%d", &map[i][j]);
dp[i][j] = -INF; //输入的工程中顺带初始化dp数组
}
}
return;
}
void DataProcess()
{
dp[1][1] = map[1][1]; //更重要的初始化
for (int i=1; i<=n; ++i)
{
for (int j=1; j<=m; ++j)
{
if (i > 1) dp[i][j] = max(dp[i][j], map[i][j] + dp[i-1][j]);
if (j > 1) dp[i][j] = max(dp[i][j], map[i][j] + dp[i][j-1]);
for (int k=1; k<j; ++k)
{
if (j % k == 0) dp[i][j] = max(dp[i][j], map[i][j] + dp[i][k]);
}
}
}
printf("%d\n", dp[n][m]);
return;
}