P1464 Function(记忆化搜索)

题目描述

对于一个递归函数w(a,b,c)w(a,b,c)

  • 如果a0 or b0 or c0就返回值1.
  • 如果a>20 or b>20 or c>20就返回w(20,20,20)
  • 如果a<b并且b<c 就返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,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)

这是个简单的递归函数,但实现起来可能会有些问题。当a,b,c均为15时,调用的次数将非常的多。你要想个办法才行.

absi2011 : 比如 w(30,-1,0)既满足条件1又满足条件2
这种时候我们就按最上面的条件来算
所以答案为1

输入格式

会有若干行。

并以-1,-1,-1结束。

保证输入的数在[9223372036854775808,9223372036854775807]之间,并且是整数。

输出格式

输出若干行,每一行格式:

w(a, b, c) = ans

注意空格。

输入输出样例

输入 #1
1 1 1
2 2 2
-1 -1 -1
输出 #1
w(1, 1, 1) = 2
w(2, 2, 2) = 4

说明/提示

记忆化搜索:(抄的百度)一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。

```cpp

#include<bits/stdc++.h>
using namespace std;
#define N 22
typedef long long ll;//将long long定义成ll,方便后面书写
ll tmp[N][N][N];//记录结果
ll a,b,c,ans;
int dfs(ll x,ll y,ll z)
{
if(x<=0||y<=0||z<=0)
return 1;
else if(x>20||y>20||z>20)
{
x=y=z=20;//防止下标越界,而且对结果没什么影响
return dfs(20, 20, 20);
}
else if(tmp[x][y][z])//如果已有出现过的答案,直接输出
return tmp[x][y][z];
else if(x<y&&y<z)
tmp[x][y][z]=dfs(x,y,z-1)+dfs(x,y-1,z-1)-dfs(x,y-1,z);
else
tmp[x][y][z]=dfs(x-1,y,z)+dfs(x-1,y,z-1)+dfs(x-1,y-1,z)-dfs(x-1,y-1,z-1);
return tmp[x][y][z];//记录答案
}
int main()
{
while(1)
{
scanf("%lld%lld%lld",&a,&b,&c);
if(a==-1&&b==-1&&c==-1)
return 0;
else
{
ans = dfs(a, b, c);
printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, ans);
}
}
}
```
posted @ 2020-12-13 20:47  屑魔女伊蕾娜  阅读(123)  评论(0)    收藏  举报