题目详情:
有n*n个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),
把所有经过 的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次。
解法:
下面三个程序,分别给出单条路最大和的递归和动态规划解法,以及两条路的递归解法;
代码如下:
#ifndef _MAX_PATHSUM_H_
#define _MAX_PATHSUM_H_
#include <assert.h>
#define MAXARRAY_SIZE 100
typedef struct tagDirection
{
int stepX;
int stepY;
}Direction, *pDirection;
/*
* The solution of recursive programming for the max sum of single path
*
*/
int FindMaxPathRecur( int grid[MAXARRAY_SIZE][MAXARRAY_SIZE], int curX, int curY,
int row, int col, pDirection dir, size_t dirCount )
{
if( curX == row - 1 && curY == col - 1 )
return grid[curX][curY];
int maxVal = -1;
for( int i = 0; i < dirCount; i++ )
{
int nextX = curX + dir[i].stepX;
int nextY = curY + dir[i].stepY;
if( nextX >= 0 && nextX < row && nextY >= 0 && nextY < col )
{
int val = grid[curX][curY] + FindMaxPathRecur( grid, nextX, nextY, row, col, dir, dirCount );
if( maxVal < val )
maxVal = val;
}
}
return maxVal;
}
/*
* The solution of recursive programming for the max sum of double path
*
*/
int FindMaxPathRecur( int grid[MAXARRAY_SIZE][MAXARRAY_SIZE], int curX1, int curY1, int curX2, int curY2,
int length, int width, pDirection dir, size_t dirCount )
{
if( curX1 == width - 1 && curY1 == length - 1
&& curX2 == width - 1 && curY2 == length - 1 )
{
return grid[length - 1][width - 1];
}
int maxVal = -1;
for( int i = 0; i < dirCount; i++ )
{
int nextX1 = curX1 + dir[i].stepY;
int nextY1 = curY1 + dir[i].stepX;
if( nextX1 >= 0 && nextX1 < width && nextY1 >= 0 && nextY1 < length )
{
for( int j = 0; j < dirCount; j++ )
{
int nextX2 = curX2 + dir[j].stepX;
int nextY2 = curY2 + dir[j].stepY;
if( nextX2 >= 0 && nextX2 < width && nextY2 >= 0 && nextY2 < length )
{
if( nextX1 == nextX2 && nextY1 == nextY2 )
{
int val = grid[nextY1][nextX1] +
FindMaxPathRecur( grid, nextX1, nextY1, nextX2, nextY2, length, width, dir, dirCount );
if( val > maxVal )
maxVal = val;
}
else
{
int val = grid[nextY1][nextX1] + grid[nextY2][nextX2] +
FindMaxPathRecur( grid, nextX1, nextY1, nextX2,nextY2, length, width, dir, dirCount );
if( val > maxVal )
maxVal = val;
}
}
}
}
}
return maxVal;
}
/*
* The solution of dynamic programming for the max sum of single path
*
*/
int FindMaxPathDP( int grid[MAXARRAY_SIZE][MAXARRAY_SIZE], int row, int col, pDirection dir, size_t dirCount )
{
int** table = new int*[row + 1];
assert( table );
for( int i = 0; i <= row; i++ )
{
table[i] = new int[ col + 1 ];
::memset( table[i], 0x00, sizeof(int)*(col + 1) );
assert( table[i] );
}
table[0][0] = grid[0][0];
for( int i = 1; i < row; i++ )
{
for( int j = 1; j < col; j++ )
{
for( int k = 0; k < dirCount; k++ )
{
if( 1 == dir[k].stepX && table[i-1][j-1] + grid[i][j-1] > table[i][j-1] )
{
table[i][j-1] = table[i-1][j-1] + grid[i][j-1];
}
else if( 1 == dir[k].stepY && table[i-1][j-1] + grid[i-1][j] > table[i-1][j] )
{
table[i-1][j] = table[i-1][j-1] + grid[i-1][j];
}
if( table[i][j-1] > table[i-1][j] )
{
table[i][j] = table[i][j-1] + grid[i][j];
}
else
{
table[i][j] = table[i-1][j] + grid[i][j];
}
}
}
}
int res = table[row-1][col-1];
for( int i = 0; i <= row; i++ )
{
delete[] table[i];
}
delete [] table;
return res;
}
void TestFindMaxPath()
{
int map[MAXARRAY_SIZE][MAXARRAY_SIZE]={
{2,0,8,20,2},
{0,0,0,0,0},
{0,13,2,0,0},
{0,10,2,0,0},
{2,0,18,0,2}};
Direction dir[2] = {{0, 1}, {1, 0} };
int row = 5;
int col = 5;
int sval = FindMaxPathRecur( map, 0, 0, row, col, dir, 2 );
int dpVal = FindMaxPathDP( map, row, col, dir, 2 );
int dval = FindMaxPathRecur( map, 0, 0, 0, 0, row, col, dir, 2 );
}
#endif