zoukankan      html  css  js  c++  java
  • 记忆化搜索:POJ1579-Function Run Fun(最基础的记忆化搜索)

    Function Run Fun
    Time Limit: 1000MS Memory Limit: 10000K
    Total Submissions: 14815 Accepted: 7659

    Description

    We all love recursion! Don't we?

    Consider a three-parameter recursive function w(a, b, c):

    if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns:
    1

    if a > 20 or b > 20 or c > 20, then w(a, b, c) returns:
    w(20, 20, 20)

    if a < b and b < c, then w(a, b, c) returns:
    w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)

    otherwise it returns:
    w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)

    This is an easy function to implement. The problem is, if implemented directly, for moderate values of a, b and c (for example, a = 15, b = 15, c = 15), the program takes hours to run because of the massive recursion.



    Input

    The input for your program will be a series of integer triples, one per line, until the end-of-file flag of -1 -1 -1. Using the above technique, you are to calculate w(a, b, c) efficiently and print the result.


    Output

    Print the value for w(a,b,c) for each triple.


    Sample Input

    1 1 1
    2 2 2
    10 4 6
    50 50 50
    -1 7 18
    -1 -1 -1



    Sample Output

    w(1, 1, 1) = 2
    w(2, 2, 2) = 4
    w(10, 4, 6) = 523
    w(50, 50, 50) = 1048576
    w(-1, 7, 18) = 1
    

     


    解题心得:

    1、这是一个很经典的记忆化搜索,算是记忆化搜索之中最简单的。其实记忆化搜索就是dp,从小到大以此往上转移。就这个题本身来说是一个很很经典的从下到上的递推。


    2、题目描述也很清楚,下一个的结果要从上一个的结果中的出,如果下一个的结果未知,那么就会产生大量的递归然后复杂度爆炸,由前到后依次得到答案,上一个答案从下一个中得出,就是动态规划一个很明显的特征。



    #include<cstring>
    #include<stdio.h>
    const int maxn = 25;
    struct num
    {
        bool flag[maxn][maxn][maxn];
        int Num[maxn][maxn][maxn];
    } N;//记录出现过的结果
    
    int w(int a,int b,int c)
    {
        //根据题意就好
        if(a <= 0 || b <= 0 || c <= 0)
            return 1;
        if(a > 20 || b > 20 || c > 20)
            return w(20,20,20);
        if(N.flag[a][b][c])
            return N.Num[a][b][c];
        if(a<b && b<c)
            return w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c);
    
        return 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()
    {
        int a,b,c;
        
        //预处理一下
        for(int i=1; i<=20; i++)
            for(int j=1; j<=20; j++)
                for(int k=1; k<=20; k++)
                {
                    a = w(i,j,k);
                    N.flag[i][j][k] = true;
                    N.Num[i][j][k] = a;
                }
                
                
        while(scanf("%d%d%d",&a,&b,&c))
        {
            if(a == -1 && b == -1 && c == -1)
                break;
            int ans = w(a,b,c);
            printf("w(%d, %d, %d) = %d
    ",a,b,c,ans);
        }
    
    

     

  • 相关阅读:
    TokenType ([{}{}()])[{}]{}
    C# netcore 开发WebService(SoapCore)
    C++求快速幂
    二分法与牛顿迭代法求方程根
    Obtaining a Thorough CS Background Online (线上CS深度学习攻略)
    Elasticsearch 堆空间配置
    S家lic
    如何用calibredrv 来merge多个cell的gds
    siliconsmart feature
    openwrt的IPTV配置
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9107325.html
Copyright © 2011-2022 走看看