记忆化搜索(洛谷P1028 P1464)

1.记忆化搜索的作用

记录每一次搜索对象的返回值,以后递归搜索中若再次出现该对象,则可直接引用之前存储的值,不必再次对该对象进行递归求值。该方法极大程度上优化了时间复杂度,减少不必要的递归。

2.如何使用

在该递归结束前(及return的上一步),使用数组记录下要return的变量。

例如:

int dfs(int x)
{
    ...
    ...
    ...
    for (......)
        ans=...
    a[x]=ans;
    return ans;
}

3.例题

       (1)洛谷P1028:数的计算       

#include<cstdio>

int N;
int a[1010];

int f(int x)
{
	int i,s=1;
	if (a[x]!=0)
		return a[x];
	for (i=x/2;i>=1;i--)                    
	{
		s+=f(i);                            
 		a[x]=s;
	}
	return s;
} 


int main()
{
	int ans;
	scanf("%d",&N);
	a[1]=1;                                 
	ans=f(N);
	printf("%d",ans);
	return 0;
}

       #代码分析
        1.for循环中s+=f(i),每一个f(i)的值都是i这个数能产生的子集数

        2.i以x/2作为初始值进入循环,s+=f(i)立即再次调用递归函数,以此类推,直到调用到1,在               逐步退出来。

        3.a[x]在从1开始逐步退出来之前,记录该次的答案。

        

        (2)洛谷P1464:Function

#include<stdio.h>
typedef long long ll;

int w[30][30][30],book[30][30][30];

int f(ll a,ll b,ll c)
{
	if (a<=0 || b<=0 || c<=0)                    //特殊情况1
		return 1;                            
	if (a>20 || b>20 || c>20)                    //特殊情况2
		return f(20,20,20);
	if (book[a][b][c]!=0)                        //记忆答案:!=0说明已搜索过,存了数值
		return w[a][b][c];
	if (a<b && b<c)
		w[a][b][c]=f(a,b,c-1)+f(a,b-1,c-1)-f(a,b-1,c);
	else 
		w[a][b][c]=f(a-1,b,c)+f(a-1,b-1,c)+f(a-1,b,c-1)-f(a-1,b-1,c-1);
	book[a][b][c]=1;
	return w[a][b][c];
}


int main()
{
	ll a,b,c;
	int ans;
	while (1)                          
	{
		scanf("%lld %lld %lld",&a,&b,&c);
		if(a==-1 && b==-1 && c==-1)
			return 0;
		ans=f(a,b,c);
		printf("w(%lld, %lld, %lld) = %d\n", a, b, c,ans);
	}
	return 0;	
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值