[各种面试题] 两条路径的最大收获

题目不太记得清了,大意是有个MXN的棋盘,然后每个格子上有一个价值,需要从左上角走到右下角再走回来,但每个格子只能走一次,请问来回的最大收获是多少。

找了个NOIP的原题:

题目链接: http://soj.me/1767

考查从 (1,1)到(m,n)找两条不相交的路径使得它们的权值和最大。

      法1:动态规划

      设 f [ k ][ i ][ j ] 表示第 k 步,第 1 条路径走到第 i 行,第 2 条路径走到第 j 行的最大权值和。
      状态转移方程:
      f [ k ][ i ][ j ] = max { f [ k - 1 ][ i - 1 ][ j ], f [ k - 1 ][ i ][ j - 1 ], f [ k - 1 ][ i ][ j ], f [ k - 1 ][ i - 1 ][ j - 1 ] } + map[ i ][ k - i ] + map[ j ][ k - j ]
      ( 2 <= k <= m + n, 1 <= i, j <= min { m, k - 1 }, i != j )

      注意起始两个格子的价值是没有计算的。


#include 
#include 
#include 
#include 
using namespace std;

int f[120][60][60];
int map[60][60];

int max(int a, int b, int c, int d)
{
    int max1, max2;
    
    max1 = max(a, b);
    max2 = max(c, d);
    
    return max(max1, max2);
}

int main()
{
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    
    int m, n;
    
    while (scanf("%d%d", &m, &n) != EOF)
    {
        for (int i = 1; i <= m; i ++)
        {
            for (int j = 1; j <= n; j ++)
            {
                scanf("%d", &map[i][j]);
            }
        }
        
        memset(f, 0, sizeof(f));
        
        for (int k = 2; k <= m + n; k ++)
        {
            for (int i = 1; i <= m && i <= k - 1; i ++)
            {
                for (int j = 1; j <= m && j <= k - 1; j ++)
                {
                    if (k != m + n && i == j)   continue;
                    
                    f[k][i][j] = max(f[k - 1][i - 1][j], f[k - 1][i][j - 1], f[k - 1][i][j], f[k - 1][i - 1][j - 1]) + map[i][k - i] + map[j][k - j];
                }
            }
        }
        
        printf("%d\n", f[m + n][m][m]);
    }
    
    return 0;
}


你可能感兴趣的:(各种面试题)