再谈记忆化搜索 HDU-1078
最近做DP题目,发现无论是LCS,还是有些题目涉及将动态规划的路径打印出来,而且有时候还要按格式输出,这个时候,记忆化搜索显得尤其重要,确实,记忆化搜索使用优化版本的动态规划,用起来思路清晰,非常方便
这个题目就是一个n*n的图里,从起点出发,只能横向或者纵向走最多k步,而且每次下个点都要比当前点的值要高,这样最终走完获得的总点权值最大是多少
明显的是一BFS 或者DFS,当然,我们稍微优化下,用记忆化搜索,就会成为很优化版本的DFS。
所以从代码看,这样的记忆化搜索,其实是从起点出发,但是最终要搜到最后一点,然后层层返回,此时,每个得到了返回值的点都已经是最优点了,所以下次再搜到这个点直接返回,这里节省了大量的时间与空间。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int G[105][105]; int dp[105][105]; int n,k; int dir[][2]={{0,1},{1,0},{0,-1},{-1,0}}; int search(int x,int y) { if (dp[x][y]>=0) return dp[x][y]; //如果已经得到最优解了,则直接返回。 int maxn=0,temp=0; for (int q=1;q<=k;q++) { int nx,ny; for (int w=0;w<4;w++) { nx=x+q*dir[w][0]; ny=y+q*dir[w][1]; if (nx<0||ny<0||nx>=n||ny>=n) continue; if (G[nx][ny]<=G[x][y]) continue; temp=search(nx,ny); if (temp>maxn) maxn=temp; //求得接下来步骤的最优解,再返回上去。 } } return dp[x][y]=G[x][y]+maxn; } int main() { while (scanf("%d%d",&n,&k)) { if (n==-1 && k==-1) break; int i,j,k; for (i=0;i<n;i++){ for (j=0;j<n;j++){ scanf("%d",&G[i][j]); } } memset(dp,-1,sizeof dp); //dp[0][0]=G[0][0]; printf("%d\n",search(0,0)); } return 0; }