记忆化搜索2018-08-04

    记忆划搜索就是指在原来搜索的基础上,进行了速度和时间上的优化,多用了一个数组来存储每一个算出来的数值,再之后用到的时候直接调用就可以了,不用再次计算。
    所以,这样可以极大地优化时间和空间。
    经典习题:斐波那契数列:相信题目描述大家已经非常清楚了,关键步骤f(n)=f(n-1)+f(n-2)。
    所以,我们可以得出一个递推的代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=10001;
int a[maxn],n;
int main(){
    cin>>n;
    a[1]=a[2]=1;
    for(int i=3;i<=n;i++)
        a[i]=a[i-1]+a[i-2];
    cout<<a[n];
    return 0;
}
    第二种思路:递归
#include <bits/stdc++.h>
using namespace std;
int f(int x){
    if(x==1||x==2)
       return 1;
    else
       return f(x-1)+f(x-2);
}
int main(){
    int n;
    cin>>n;
    cout<<f(n);
    return 0;
}
    第三种思路:记忆化搜索:这里每算一个f(n)就要算f(n-1)和f(n-2),如果是f(5),就要算f(4)和f(3),而在算f(4)的时候,要算f(3)和f(2),而这里,我们可以发现,在算f(4)+f(3)的时候,显然,再算f(4)的时候,f(3)就已经被算过了,为了不让f(3)再被重新算一次,用数组在计算的同时存下f(3)的值,到时候重新调用就是了,代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=10000+3;
int a[maxn];
int f(int x){
    if(x==1||x==2)
       return 1;
    if(a[x])
       return a[x];
    else
       return a[x]=f(x-1)+f(x-2);
}
int main(){
    int n;
    a[1]=a[2]=1;
    cin>>n;
    cout<<f(n);
    return 0;
}

这样,我们就可以利用记忆化搜索来做题了!
https://www.luogu.org/problemnew/show/P1464
这一道题就是纯粹地让我们来练习记忆化搜索的,直接按照题目的意思,运用记忆化搜索,很快就能做出来了。

#include <bits/stdc++.h>
using namespace std;
const int maxn=50;
int p[maxn][maxn][maxn];
long long w(long long a,long long b,long long c){
    if(a<=0||b<=0||c<=0)
       return 1;
    else if(a>20||b>20||c>20)
       return w(20,20,20);
    if(p[a][b][c]==1)
       return p[a][b][c];
    if(a<b&&b<c)
       return p[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
    else
       return p[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
int main(){
    long long a,b,c;
    while(1){
        cin>>a>>b>>c;
        if(a==-1&&b==-1&&c==-1)
           break;
        printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,w(a,b,c));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42875611/article/details/81432098