题解 P1464【Function】

依愚之见,本题的难点在于记忆化搜索以及数据结构的存储。


\[First:\text{存储变量}\]
由于\(w\)函数有三个参数:\(a,b,c\)。所以,我们可以设数组\(f\),那\(f\)设成几维的呢?我认为应该设成三维的,即\(f[][][]\),再观察数据范围:
\[\text{保证输入的数在[-9223372036854775808,9223372036854775807]之间}\]
什么?范围这么大??那按道理来讲应该设一个想像这样大的数组:
\[f[9223372036854775807][9223372036854775807][9223372036854775807]\]

这早就暴空间(\(MLE\))了,搞不好\(luogu\)评测机给你搞搞坏掉,并且输入的数还有负数,\(∴\)这种数据存储的方法是错误滴\(!\)

那如何使用正确的方法存储数据呢?
我们一起看看题目:

如果 $ a \leq 0 or b \leq 0 or c \leq 0$ 就返回值 \(1\).
如果\(a>20 or b>20 or c>20\)就返回\(w(20,20,20)\)

所以,我们可以给出以下操作来初始化:
\(1.\)当$ a \leq 0 or b \leq 0 or c \leq 0$ 时,直接 \(cout<<1\)
\(2.\)\(a>20 or b>20 or c>20\)时,执行\(w(20,20,20)\)\(cout\)它。
\(3.\)其它情况直接\(cout<<w(a,b,c)\)
根据分析:就可知:\(f\)数组最大只需要开\(21\),我因个人喜好,就开\(25\)\(QAQ\)
给出该代码部分的代码实现\(↓↓↓\)

while(cin>>a>>b>>c) //不断输入a,b,c
{
    if(a==-1 && b==-1 && c==-1) return 0;  //输入结束
    else if (a<=0 || b<=0 ||c<=0 ) cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<<1<<endl;
    else if(a>20 || b>20 ||c>20) cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<<w(20,20,20)<<endl;
    else cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<<w(a,b,c)<<endl;
}

\[Second:\text{记忆化搜索}\]
暴力搜索十分简单,按照题目的意思一句一句打就好了,不解释,给出代码:

inline int w(int a,int b,int c)
{
    if(a<=0 ||b<=0 ||c<=0) return 1;
    else if(a>20 ||b>20 ||c>20) return w(20,20,20);
    else if(a<b && b<c) return w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c-1);
    else f[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);
}

这道题的关键在于记忆化搜索,其实记忆化搜索没有我们想的那么高深,将\(f\)数组带入函数即可(别忘了将\(f\)数组初始化),具体情节如下:

inline int w(int a,int b,int c)
{
    if(f[a][b][c]!=-1) return f[a][b][c];
    if(a<=0 ||b<=0 ||c<=0) return f[a][b][c]=1;
    else if(a>20 ||b>20 ||c>20) return f[a][b][c]=w(20,20,20);
    else if(a<b && b<c) return f[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c-1);
    else return f[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);
}


memset(f,-1,sizeof(f)); //(在 int main()中

本题还有一个坑点在于输出的空格,我就因这个原因下载了一次数据(我太弱了QAQ),祝大家不要和我踩同一个坑.好了本题解到此为止。给出最终代码,如下\(:\)

#include<bits/stdc++.h>  //无敌的万能头
using namespace std;
int f[25][25][25];
inline int w(int a,int b,int c)
{
    if(f[a][b][c]!=-1) return f[a][b][c];
    if(a<=0 ||b<=0 ||c<=0) return f[a][b][c]=1;
    else if(a>20 ||b>20 ||c>20) return f[a][b][c]=w(20,20,20);
    else if(a<b && b<c) return f[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c-1);
    else return f[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;   //别忘开long long
    memset(f,-1,sizeof(f));
    while(cin>>a>>b>>c)
    {
        if(a==-1 && b==-1 && c==-1) return 0;
        else if (a<=0 || b<=0 ||c<=0 ) cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<<1<<endl;
        else if(a>20 || b>20 ||c>20) cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<<w(20,20,20)<<endl;
        else cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<<w(a,b,c)<<endl;
    }
    return 0;//完美的结束QAQ
}

猜你喜欢

转载自www.cnblogs.com/Luke-Skywalker/p/11227528.html
今日推荐