題目詳情:
有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