记忆化搜索与DP算法区别与联系

个人见解
DP(从零开始 ):
首先找对“零”点(起始点),一般要使用逆向思维寻找,从真正的起始点(一般与规定的起点相反)开始类似于找规律。简单明了;
记忆化搜索(递归):
“暴力”解法,从规定起始点开始把所有情况进行记忆和搜索,记忆化搜索比直接暴力搜索要快,因为每个点只跑一次且记录下从该点开始跑的最优解;

例题
题目描述
正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一直处在饥饿的状态中。某日上课,正当他饿得头昏眼花之时,眼前突然闪现出了一个nm(n and m<=200)的矩型的巨型大餐桌,而自己正处在这个大餐桌的一侧的中点下边。餐桌被划分为了nm个小方格,每一个方格中都有一个圆形的巨型大餐盘,上面盛满了令李大水牛朝思暮想的食物。李大水牛已将餐桌上所有的食物按其所能提供的能量打了分(有些是负的,因为吃了要拉肚子),他决定从自己所处的位置吃到餐桌的另一侧,但他吃东西有一个习惯——只吃自己前方或左前方或右前方的盘中的食物。
每组数据的出发点都是最后一行的中间位置的下方!

输入格式
[输入数据:]

第一行为m n.(n为奇数),李大水牛一开始在最后一行的中间的下方

接下来为m*n的数字距阵.

共有m行,每行n个数字.数字间用空格隔开.代表该格子上的盘中的食物所能提供的能量.

数字全是整数.

输出格式

一个数,为你所找出的最大能量值.

输入输出样例
输入 #1 复制
6 7
16 4 3 12 6 0 3
4 -5 6 7 0 0 2
6 0 -1 -2 3 6 8
5 3 4 0 0 -2 7
-1 7 4 0 7 -5 6
0 -1 3 4 12 4 2
输出 #1 复制
41

//此题我使用两种做法,实际上只是思路的顺序不同而已。
//DP是使用从上到下而记忆化搜索是从下到上因为递归速度慢所以此题AC代码为DP解法
 
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[1000][1000];
int b[1000][1000];
long long n,m;
int dfs(int i,int j){
	if(b[i][j])return b[i][j];
	if(i<1||j>m)return 0;
	return 	b[i][j]=a[i][j]+max(max(dfs(i-1,j),dfs(i-1,j-1)),dfs(i-1,j+1));
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
	}
}
//正确解法 
//	for(int i=1;i<=n;i++){
//		for(int j=1;j<=m;j++){
//			a[i][j]=max(max(a[i-1][j],a[i-1][j-1]),a[i-1][j+1])+a[i][j]; 
//		}
//	}
//	cout<<max(max(a[n][m/2],a[n][m/2+1]),a[n][m/2+2]);
	for(int i=m;i>0;i--){
		b[n][i]=a[n][i]+max(max(dfs(n-1,i),dfs(n-1,i-1)),dfs(n-1,i+1));
	}
	cout<<max(max(b[n][m/2],b[n][m/2+1]),b[n][m/2+2]);
	return 0;
}

总结
DP是由一开始的点逐步加到最后,局部最优到全局最优。
记忆化搜索思想上也是从局部开始但是运算顺序不一样从全局开始往后推。相比较DP而言所需内存和时间都过大。

发布了93 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43813373/article/details/103977338