https://www.luogu.com.cn/problem/P1464
考点:记忆化搜索、递归、map
题意:
按照题目要求写递归函数。
解法:
在函数开始时查看哈希表中是否已经有答案记录,如果有就直接返回。如果没有答案,则正常执行,返回前把答案添加到哈希表,记忆化搜索可以大幅度提高递归的效率。
实际上是水题,但是我卡了挺长时间的,原因是对STL的map不熟悉。我自定义了一个三元组类用来表示3个参数,是类似pair的数据结构。
struct TT {
ll a,b,c;
TT(ll x, ll y, ll z) {
a=x; b=y; c=z;
}
bool operator<(const TT &t) const {
if (a != t.a) return a < t.a;
if (b != t.b) return b < t.b;
return c < t.c;
}
};
对于自定义类作为map的键的时候,必须重载小于运算符,而且不能乱写,我一开始只对比了a的值,导致map索引失败。正确做法应该是依次比较abc的值。
完整代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct TT {
ll a,b,c;
TT(ll x, ll y, ll z) {
a=x; b=y; c=z;
}
bool operator<(const TT &t) const {
if (a != t.a) return a < t.a;
if (b != t.b) return b < t.b;
return c < t.c;
}
};
map<TT, ll> M;
ll w(ll a, ll b, ll c) {
if (M.find({a,b,c}) != M.end()) return M[{a,b,c}];
if (a <= 0 || b <= 0 || c <= 0) {
M[{a,b,c}] = 1;
return 1;
}
if (a > 20 || b > 20 || c > 20) {
ll res = w(20, 20, 20);
M[{a,b,c}] = res;
return res;
}
if (a < b && b < c) {
ll res = w(a,b,c-1) + w(a,b-1,c-1) - w(a,b-1,c);
M[{a,b,c}] = res;
return res;
}
ll res = w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
M[{a,b,c}] = res;
return res;
}
int main() {
ll a,b,c;
while (cin >> a >> b >> c) {
if (a == -1 && b == -1 && c == -1) break;
cout << "w(" << a << ", " << b << ", " << c << ") = " << w(a,b,c) << endl;
}
return 0;
}