记忆化搜索

今天的时间较短,没有刷很多的题,只刷了一道记忆化搜索的题目,还调试了半天(就是因为输出没有换行TwT)。但就是这道题让我把新手村A掉啦~\(≧▽≦)/~

记忆化搜索

·记忆化搜索是啥?

  所谓记忆化搜索,就是让程序实现自动记忆已经搜索过的东西,这样如果再次搜到这个东西,就可以直接调用了。

·记忆化搜索与dp的不同点:

  dp需要对每个状态进行遍历,而记忆化搜索则可以排除无用状态。更重要的是,记忆化搜索还可以剪枝,这样一来,就大大降低了空间复杂度。

·接下来就是我调了半天的题了:

  相信大家一定都做过,这道题就是大名鼎鼎的“function”。

  题目描述: 

    定义一个递归函数w(a,b,c),递归条件是这样的:

    (1)如果a \le 0a0 or b \le 0b0 or c \le 0c0就返回值11.

    (2)如果a>20a>20 or b>20b>20 or c>20c>20就返回w(20,20,20)w(20,20,20)

    (3)如果a<ba<b并且b<cb<c 就返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c)w(a,b,c1)+w(a,b1,c1)w(a,b1,c)

    (4)其它的情况就返回w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)w(a1,b,c)+w(a1,b1,c)+w(a1,b,c1)w(a1,b1,c1)

    这是一个简单的递归函数,但是实现起来可能会有些问题,比如当a、b、c都是15的时候调用的次数非常多,必须想一个办法!

  题目分析:

    这个办法就是“记忆化搜索”。根据(2)可以初步确定要将20以内的状态存下来,这样一来,每次遍历到这个状态时,就不用再去计算,直接返回已经存好的状态就可以啦!

  代码实现:

 1 #include<cstdio>
 2 #include<iostream>
 3 #define ll long long
 4   
 5 using namespace std;
 6   
 7 ll a,b,c;
 8 ll ans[30][30][30];
 9 
10 ll function(ll x,ll y,ll z)
11 {
12      if(x<=0||y<=0||z<=0) return 1;
13      if(x>20||y>20||z>20) return function(20,20,20);
14      if(ans[x][y][z]!=0) return ans[x][y][z];//如果这个情况已经被存在了ans数组中,那么就直接返回此状态下数组的值
15      if(x<y&&y<z) ans[x][y][z]=function(x,y,z-1)+function(x,y-1,z-1)-function(x,y-1,z);
16      else return ans[x][y][z]=function(x-1,y,z)+function(x-1,y-1,z)+function(x-1,y,z-1)-function(x-1,y-1,z-1);//将各种状态存到ans数组中
17      return ans[x][y][z];
18 }
19  
20 int main()
21 {
22     while(1)//如果不在循环中加上return 0,就会一直不停的读下去
23     {
24         scanf("%lld%lld%lld",&a,&b,&c);
25         if(a==-1&&b==-1&&c==-1) return 0;读到-1,-1,-1时直接结束程序
26         printf("w(%lld, %lld, %lld) = ",a,b,c);
27         if(a>20) a=21;
28         if(b>20) b=21;
29         if(c>20) c=21;//减少不必要的计算
30         printf("%lld\n",function(a,b,c));
31     }
32 }

 ·总结:

  记忆化搜索本质上是一种dp思想,但是又比dp快一点的算法,可以运用在在考试和平时做题时。  

  对了,还有一件事,一定要看好输出格式,比如这道题我就没有换行,导致WA了三次TwT。

posted @ 2019-06-10 07:14  蒟蒻hqk  阅读(1129)  评论(0编辑  收藏  举报