这几日正好在看《算法导论》,对其中的一道习题做了C实现,题目详见220页,第15-6题。
动态规划的基本思想就是降低问题的规模,通过迭代或者递归的方式求解子问题,自底向上推出目标结果。
cipher感觉动态规划就是遵守问题约束的穷举,计算规模自然比较小。
基本思路就是:
M[ i, j ] = p( i, j ) + max( M[ i - 1, j - 1 ], M[ i - 1, j ], M[ i -1, j + 1 ] )
M表示每走一步的获利, p表示每个格子的利润(实现中随机生成),M[ i, j ]可能来自于他的左下方、下放和右下方中最大的一个。
下面给出代码,定义了一个6*6的棋盘:
#include <iostream>
#include <stdlib.h>
#include <time.h>
#define N 6
using namespace std;
// 递归获得路径
void reprintPath( char path[][ N ], int i, int j )
{
int temp = j;
if( i < 0 ) {
cout << i + 1 << ", " << j << endl;
} else {
if( path[ i ][ j ] == 'L' )
temp = j - 1;
if( path[ i ][ j ] == 'R' )
temp = j + 1;
reprintPath( path, i - 1, temp );
cout << i + 1 << ", " << j << endl;
}
}
// 迭代获得路径
void printPath( char path[][ N ], int i, int j )
{
for( int m = i; i >= 0; -- i ) {
cout << "Path " << i + 1 <<
" ( " << i + 1 << ", " << j << " )" << endl;
if( path[ i ][ j ] == 'L' ) {
-- j;
}
if( path[ i ][ j ] == 'R' ) {
++ j;
}
}
cout << "Path " << i + 1 << " ( " << i + 1 << ", " << j << " )" << endl;
}
int main()
{
// srand( time( NULL ) );
int board[ N ][ N ];
char path[ N - 1 ][ N ];
int tempValue = 0;
char tempPath ='N';
int flag = 0;
// 随机生成每个各自的获利
for( int i = 0; i != N; ++ i ) {
for( int j = 0; j != N; ++ j ) {
board[ i ][ j ] = rand() % 10 + 1;
}
}
// 初始化path数组,该数组用来获得路径
for( int i = 0; i != N - 1; ++ i ) {
for( int j = 0; j != N; ++ j ) {
path[ i ][ j ] = 'N';
}
}
for( int i = 0; i != N; ++ i ) {
for( int j = 0; j != N; ++ j ) {
cout << board[ i ][ j ] << " ";
}
cout << endl;
}
// 循环从1开始,第一行不做考虑
for( int i = 1; i != N; ++ i ) {
// 第一列只有两种情况
if( board[ i - 1 ][ 0 ] >= board[ i - 1 ][ 1 ] ) {
board[ i ][ 0 ] += board[ i - 1 ][ 0 ];
path[ i - 1 ][ 0 ] = 'U';
} else {
board[ i ][ 0 ] += board[ i - 1 ][ 1 ];
path[ i - 1 ][ 0 ] = 'R';
}
// 第2到N-2列有三种情况
for( int j = 1; j != N - 1; ++ j ) {
if( board[ i - 1 ][ j - 1 ] >= board[ i - 1 ][ j ] ) {
tempValue = board[ i - 1 ][ j - 1 ];
tempPath = 'L';
} else {
tempValue = board[ i - 1 ][ j ];
tempPath = 'U';
}
if( tempValue >= board[ i - 1 ][ j + 1 ] ) {
board[ i ][ j ] += tempValue;
path[ i - 1 ][ j ] = tempPath;
} else {
board[ i ][ j ] += board[ i - 1 ][ j + 1 ];
path[ i - 1 ][ j ] = 'R';
}
}
// N-1列的两种情况
if( board[ i - 1 ][ N - 1 ] >= board[ i - 1 ][ N - 2 ] ) {
board[ i ][ N - 1 ] += board[ i - 1 ][ N - 1 ];
path[ i - 1 ][ N - 1 ] = 'U';
} else {
board[ i ][ N - 1 ] += board[ i - 1 ][ N - 2 ];
path[ i - 1 ][ N - 1 ] = 'L';
}
}
for( int i = 0; i != N; ++ i ) {
for( int j = 0; j != N; ++ j ) {
cout << board[ i ][ j ] << " ";
}
cout << endl;
}
for( int i = 0; i != N - 1; ++ i ) {
for( int j = 0; j != N; ++ j ) {
cout << path[ i ][ j ] << " ";
}
cout << endl;
}
tempValue = 0;
for( int i = 0; i != N; ++ i ) {
if( tempValue < board[ 5 ][ i ] ) {
tempValue = board[ 5 ][ i ];
flag = i;
}
}
printPath( path, 4, flag );
reprintPath( path, 4, flag );
cout << "the bigest one -> " << flag << endl;
}