LightOJ - 1071 Baker Vai(记忆化搜索)

来源:互联网 发布:多商网淘宝代销赚钱吗 编辑:程序博客网 时间:2024/05/01 19:02

题目大意:给你一个n * m的矩阵,矩阵上面有对应的数字,起始位置是(1,1)
现在要求你从起始位置走到终点(n,m),只能往右或者往下走,接着从终点走回起始位置,只能往上或者往左走,每个格子只能被走一次,问能得到的数字的最大和是多少

解题思路:从终点往回走,就相当于从起点往终点走,所以就当成从起点走两条不相交的路走到终点
因为只能往右或者往下,所以走的步数最多是n + m - 2
接着设dp[step][row1][row2]表示走了step步,第一条线路走到了row1行,第二条线路走到了row2行之后所能得到的最大数值和是多少
接着枚举每条线路的方向,进行记忆化搜索即可
现在的问题是,怎么判断走到同一个位置了,其实很简单,只要判断一下row1是否等于row2即可,因为所走的步数是一样的,减去行之后,就可以得到列的位置了,所以当row1 == row2时,就走到同一个地方了,这种就要剪掉

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int N = 110;int val[N][N], dp[2 * N][N][N];int n, m, cas = 1;int dfs(int step, int row1, int row2) {    if (row1 == row2 && !(row1 == 0 || row1 == n - 1)) return -INF;    if (step == n + m - 2 && row1 == row2 && row1 == n - 1) return val[n - 1][m - 1];    if (~dp[step][row1][row2]) return dp[step][row1][row2];    int ans = -INF;    //都往下走    if (row1 + 1 < n && row2 + 1 < n)         ans = max(ans, dfs(step + 1, row1 + 1, row2 + 1));    //下右    if (row1 + 1 < n && step - row2 + 1 < m)        ans = max(ans, dfs(step + 1, row1 + 1, row2));    //右右    if (step - row1 + 1 < m && step - row2 + 1 < m)        ans = max(ans, dfs(step + 1, row1, row2));    //右下    if (step - row1 + 1 < m && row2 + 1 < n)        ans = max(ans, dfs(step + 1, row1, row2 + 1));    ans += val[row1][step - row1];    if (row1 != row2)        ans += val[row2][step - row2];    return dp[step][row1][row2] = ans;}void solve (){    scanf("%d%d", &n, &m);    for (int i = 0; i < n; i++)        for (int j = 0; j < m; j++)            scanf("%d", &val[i][j]);    memset(dp, -1, sizeof (dp));    printf("Case %d: %d\n", cas++, dfs(0, 0, 0));}int main() {    int test;    scanf("%d", &test);    while (test--) solve();    return 0;}
0 0
原创粉丝点击