POJ 1088 动态规划
今天晚上自习学习算法,这里就温故知新写一篇动归的博客
本题题目为汉语,此处就不翻译了
解题思路:本题按照题意可以很容易的看出这是一道典型的动态规划的题目。无非就是求出每个点周围可以达到最大长度的点,依次继续。本题目比较适合递归来进行动态规划。
动态规划方程:f[i][j] = max{f[i][j-1],f[i][j+1],f[i-1][j],f[i+1][j]}+1
其中f[i][j]表示第i行第j列能达到的最大长度
代码如下:
#include<iostream>
#define N 101
using namespace std;
int r,c;
int a[N][N];
int len[N][N];
int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int getLen(int x,int y){
if(len[x][y]!=0) return len[x][y];
int max1 = 0,s;
for(int i = 0;i<4;i++){
int tx = x+dir[i][0];
int ty = y+dir[i][1];
if(tx>0&&tx<=c&&ty>0&&ty<=r&&a[x][y]>a[tx][ty]){
s = getLen(tx,ty);
if(max1<s)
max1 = s;
}
}
len[x][y] = max1+1;
return max1+1;
}
int main(){
cin>>r>>c;
for(int i = 1;i<=r;i++){
for(int j = 1;j<=c;j++){
cin>>a[i][j];
}
}
for(int i = 1;i<=r;i++){
for(int j = 1;j<=c;j++){
len[i][j] = getLen(i,j);
}
}
int s = -10000;
for(int i = 1;i<=r;i++){
for(int j = 1;j<=c;j++){
if(len[i][j]>s)
s = len[i][j];
}
}
cout<<s<<endl;
return 0;
}
动归算法性质的必要性分析:
子问题独立
这里每个点只需要找其周围四个点的最大长度值。
边界设置
tx>0&&tx<=c&&ty>0&&ty<=r
备忘录
len[x][y] = max1+1;
上边的代码定义了一个dir数组来进行对一个点周围4个点进行循环,是一个我之前知道却不常用的小技巧,感觉还是很不错的。代码还是需要多借鉴才能尽快的掌握更多的技巧,爬上巨人的肩膀总比创造一个巨人容易。