对于一个递归函数w(a,b,c)
这种时候我们就按最上面的条件来算
所以答案为1
/*
会有若干行。
并以-1,-1,-1?1,?1,?1结束。
保证输入的数在[?9223372036854775808,9223372036854775807]之间,并且是整数。
输出若干行,每一行格式:
w(a, b, c) = ans
注意空格。
1 1 1
2 2 2
-1 -1 -1
w(1, 1, 1) = 2
w(2, 2, 2) = 4
记忆化搜索
这个题目已经告诉我们用记忆化搜索了。。。在此之前我们先看看如何记忆化搜索斐波那契数列。
斐波那契数列满足 f(n) = f(n-1) + f(n-2) 如果当 n 很大时按照平常的递归代码:
#include <iostream>
#include <cstring>
#define ll long long
using namespace std ;
ll f( ll n ){
if ( n == 0 ){
return 0 ;
}else if ( n == 1 || n == 2 ){
return 1 ;
}
return f(n - 1) + f(n - 2) ;
}
int main(){
ll n ;
while ( cin >> n ) {
cout << f(n) << endl ;
}
}
当 n 到 36 左右时速度已经明显变慢。如果采用记忆化搜索的办法呢?代码如下:
#include <iostream>
#define ll long long
using namespace std ;
const int MAXN = 305 ;
ll ans[MAXN] ;
ll f( ll n ){
if ( n == 0 ){
return 0 ;
}else if ( n == 1 || n == 2 ){
return 1 ;
}else if ( ans[n] != 0 ){
return ans[n] ;
}
return ans[n] = f(n - 1) + f(n - 2) ;
}
int main(){
ll n ;
while ( cin >> n ){
memset(ans , 0 , sizeof(ans)) ;
cout << f(n) << endl ;
}
}
当 n 大于 36 甚至到 90 左右(快炸 long long 了..)都能瞬间出答案。所以记忆化搜索的思想就是记录下每一次计算的答案,如果这个值存在的话就直接返回这个值,省去了递归中重复计算的过程,可以省去大量的时间,这或许也是个用空间换时间的一个典型例子。
所以本道题也可以用记忆化搜索的思想去解决,记录中间结果减少重复计算从而省去大量时间。代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <utility>
#define ll long long
using namespace std ;
ll ans[25][25][25] ;
void init(){
for ( int i = 0 ; i < 25 ; i ++ ){
for ( int j = 0 ; j < 25 ; j ++ ){
for ( int k = 0 ; k < 25 ; k ++ ){
ans[i][j][k] = -1 ;
}
}
}
return ;
}
ll w ( ll a , ll b , ll c ){
if ( a <= 0 || b <= 0 || c <= 0 ){
return 1 ;
}else if ( ans[a][b][c] != -1 ){
return ans[a][b][c] ;
}else if ( a > 20 || b > 20 || c > 20 ){
ans[a][b][c] = w(20 , 20 , 20) ;
}else if ( a < b && b < c ){
ans[a][b][c] = w(a , b , c - 1 ) + w(a , b - 1 , c - 1) - w(a , b - 1 , c) ;
}else{
ans[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) ;
}
return ans[a][b][c] ;
}
int main(){
ll a , b , c ;
while ( cin >> a >> b >> c && !(a == -1 && b == -1 && c == -1) ){
init() ;
printf("w(%lld, %lld, %lld) = " , a , b , c) ;
if ( a > 20 ) a = 21 ;
if ( b > 20 ) b = 21 ;
if ( c > 20 ) c = 21 ;
printf("%lld\n" , w(a , b , c)) ;
}
return 0 ;
}
原文:https://www.cnblogs.com/Cantredo/p/9784645.html