记忆化搜索入门——洛谷 [p1646]题解

记忆化搜索的思路:

记忆化搜索就是我们记录一下每一个函数的值,比如说在这个题目中我们算出了 $ w(x,y,z) $ 那么我们就用一个数组 $ f[x][y][z] $ 来记录这个函数在参数为 $ x,y,z $ 的时候的值,这样我们下次递归到这里的时候我们直需要调用这个值而无需递归下去求解。
而且由于这个地方的我们可以发现只需要需要 $ f[i][j][k],0 \le i \le 20.0 \le j \le 20,0 \le k \le 20 $ 的值就可以了

需要注意的地方:

在进行记忆化搜索的时候,一定要注意下标越界的问题,并且我们在记忆化搜索的时候一定要注意把递归到的值存入数组。比如说今天就忘了存。还有我们要考虑那些只需要存比如说当 $ f[i][j][k] $ 中的 $ i $ 大于 $ 20 $ 的时候我们就没有必要存了。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

long long a,b,c;
long long f[50][50][50];

long long fuc(long long x,long long y,long long z)
{
    if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0)
        if(f[x][y][z]!=0) return f[x][y][z]; //记忆化搜索的重要地方
    
    if(x<=0 || y<=0 || z<=0){
        if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0) 
            return f[x][y][z]=1; 
        else return 1;
    }
    else if(x>20 || y>20 ||z>20) 
        return f[20][20][20]=fuc(20,20,20);
    else if(a<b && b<c){ 
        if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0)
            return f[x][y][z]=fuc(x,y,z-1)+fuc(x,y-1,z-1)-fuc(x,y-1,z); 
        else return fuc(x,y,z-1)+fuc(x,y-1,z-1)-fuc(x,y-1,z); 
    }
    else if(x<=20 && x>=0 && y<=20 && y>=0 && z<=20 && z>=0) 
        return f[x][y][z]=fuc(x-1,y,z)+fuc(x-1,y-1,z)+fuc(x-1,y,z-1)-fuc(x-1,y-1,z-1); 
    else return fuc(x-1,y,z)+fuc(x-1,y-1,z)+fuc(x-1,y,z-1)-fuc(x-1,y-1,z-1);
}

int main()
{   
    while(true){
        scanf("%lld %lld %lld",& a,& b,& c);
        if(a==-1 && b==-1 && c==-1) break;
        printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,fuc(a,b,c));
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lixiao189/p/9556424.html