/* // 典型的动态规划,用递归下的记忆化搜索来实现,得用递归,因为你根本不知道从哪里开始,即cnt[0][0]不知道是多少 // 状态转移方程 合法的情况下:DP(i,j) = max( DP(i,j-1), DP(i,j+1), DP(i-1,j), DP(i+1,j) ) + 1; #include <iostream> using namespace std; const int m_size = 105; int cnt[m_size][m_size],matrix[m_size][m_size]; int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; int row,col; bool ok(const int &x,const int &y) { return (x>=0&&x<row && y>=0&&y<col); } // 如果已经处理过,直接返回(记忆化搜索效率之所以高的原因:不重复计算) int dp(const int &x,const int &y) { // 将结果记录在cnt数组中(记忆化搜索的重点) // 如果左右上下都没有一个点的值比这个点的值大,则cnt[i][j] = max+1 = 1 // 否则将左右上下各点最大滑雪长度记录在max中, 则cnt[i][j] = max+1 // 这就是max为什么要初始化为0的原因. int dx,dy,i; int max = 0; if(cnt[x][y]>0) return cnt[x][y]; for(i=0;i<4;i++) { dx = x + dir[i][0]; dy = y + dir[i][1]; if(ok(dx,dy) &&matrix[x][y]>matrix[dx][dy] ) { if(max<dp(dx,dy)) max = dp(dx,dy); } } return (cnt[x][y] = max + 1); } void print_max() { int i,j; for(i=0;i<row;i++) for(j=0;j<col;j++) if(cnt[0][0]<cnt[i][j]) cnt[0][0] = cnt[i][j]; cout << cnt[0][0] << endl; } int main() { int i,j; while(cin>>row) { cin >> col; for(i=0;i<row;i++) for(j=0;j<col;j++) { cin >> matrix[i][j]; cnt[i][j] = 0; } for(i=0;i<row;i++) for(j=0;j<col;j++) { dp(i,j); } print_max(); } }
这是滑雪球问题,dp + 类似图的搜索,动态规划关键在于根据题意定义dp的含义 和 写出状态转移方程。