首页 > 代码库 > hdu--1978--记忆化深度搜索||递推

hdu--1978--记忆化深度搜索||递推

这题 我开始的做法是 记忆化搜索  但是tm地竟然tle了。。。很想不通 因为数据很小啊 就100 虽然方案的总数可能会很大..

然后 我就去百度 记忆化搜索 看下是不是我用错方法了 事实证明 我虽然没有用错 但还是 学到了很多=-=、

其实  我很早以前 也看过关于 记忆化搜索的一些介绍 但是 并没有太多感觉 并不是那些作者写的不好 而是我的水平没到 感受不了。。

很多东西会在不知不觉中提升~

我想 将我读的这篇介绍 传到这篇博客里来 似乎只能上传照片和视频=-=   那我给个链接吧  传送

虽然里面的代码不是用C/C++写的 但其实不会太影响我们的阅读 重点是对于 动态规划 与 搜索思想的理解

------------touch  me

然后 我继续回过头来检查自己的TLE代码 我去discuss里看了下别人的讨论 发现很多人用的都是 递推式的动态规划做的 看到了一个和我用相同的记忆化深搜做的

and then  i got it

我对于maze[i][j]的处理太懒了...耗了太多时间..

我将tle与改后AC代码都放上来吧

 1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4  5 int n , m; 6 const int mod = 10000; 7 const int size = 110; 8 int maze[size][size]; 9 int dp[size][size];10 bool vis[size][size];11 12 int dfs( int x , int y )13 {14     if( x==n && y==m )15         return 1;16     if( vis[x][y] )17         return dp[x][y];18     if( maze[x][y]==0 )19         return 0;20     for( int i = x ; i<=n ; i++ )21     {22         for( int j = y ; j<=m ; j++ )23         {24             if( (i-x + j-y) > maze[x][y] || x==i && y==j )25                 continue;26             else27             {28                 dp[x][y] += dfs(i,j);29                 if( dp[x][y]>=mod )30                     dp[x][y] %= mod;31             }32         }33     }34     vis[x][y] = true;35     return dp[x][y];36 }37 38 int main()39 {40     cin.sync_with_stdio(false);41     int t , ans;42     while( cin >> t )43     {44         while( t-- )45         {46             memset( vis , false , sizeof(vis) );47             memset( dp , 0 , sizeof(dp) );48             cin >> n >> m;49             for( int i = 1 ; i<=n ; i++ )50             {51                 for( int j = 1 ; j<=m ; j++ )52                 {53                     cin >> maze[i][j];54                 }55             }56             ans = dfs(1,1);57             cout << ans << endl;58         }59     }60     return 0;61 }
View Code

*** 其实 vis数组 是可以不写的 因为完全可以通过if( dp[ x ] [ y ])return dp[x][y]来做到 但是我习惯上 有时候会写上它 有助于理解

 1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4  5 int n , m; 6 const int mod = 10000; 7 const int size = 110; 8 int maze[size][size]; 9 int dp[size][size];10 bool vis[size][size];11 12 int dfs( int x , int y )13 {14     if( x==n && y==m )15         return 1;16     if( vis[x][y] )17     {18         return dp[x][y];19     }20     if( maze[x][y]==0 )21         return 0;22     for( int i = 0 ; i<=maze[x][y] ; i++ )23     {24         for( int j = 0 ; j+i<=maze[x][y] ; j++ )25         {26             if( !(i+j) || x+i>n || y+j>m )27                 continue;28             else29             {30                 dp[x][y] += dfs( x+i,y+j);31                 if( dp[x][y]>=mod )32                     dp[x][y] %= mod;33             }34         }35     }36     vis[x][y] = true;37     return dp[x][y];38 }39 40 int main()41 {42     cin.sync_with_stdio(false);43     int t , ans;44     while( cin >> t )45     {46         while( t-- )47         {48             memset( vis , false , sizeof(vis) );49             memset( dp , 0 , sizeof(dp) );50             cin >> n >> m;51             for( int i = 1 ; i<=n ; i++ )52             {53                 for( int j = 1 ; j<=m ; j++ )54                 {55                     cin >> maze[i][j];56                 }57             }58             ans = dfs(1,1);59             cout << ans << endl;60         }61     }62     return 0;63 }
View Code

 

稍微 解释下 有助于 初学者的我们来理解:

因为是 深搜 所以这是递归的 我们可以将dp[ x ] [ y ]看成在N * M的地图里有多少种方式从(N,M)这个终点走到(X,Y)这个点 然后你可能会遇到dp[ x1 ] [ y1 ]与dp[ X2 ][ y2]都需要求得dp[ x3 ][ y3 ]那么我们只要将这个值给保存下来 在(x1,y1),(x2,y2)需要的时候 直接给它们就可以了 这里就有着DP对于重叠子问题的处理 而递归又是深搜的体现

这里 有一个边界注意下 就是(N,M) 当你搜索到这个点时 就可以看成是 递归出口了 然后直接返回一个 1 就可以了

 

我们再来讲下 递推的处理

这就和递归 完全2个方向 可以这样想 一个是 自底向上 一个是顶向下 dp[ x ][ y ]就变成了是N*M的地图里有多少种方式从(1,1)走到(x,y)这个点

其余多的解释 我也讲不来了 并且 我不确认 我以上所讲 都是正确的 都是我自己的理解 欢迎 探讨=-=

 1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4  5 const int size = 110; 6 const int mod = 10000; 7 int maze[size][size]; 8 int dp[size][size]; 9 10 int main()11 {12     cin.sync_with_stdio(false);13     int n , m , t;14     while( cin >> t )15     {16         while( t-- )17         {18             cin >> n >> m;19             for( int i = 1 ; i<=n ; i++ )20             {21                 for( int j = 1 ; j<=m ; j++ )22                 {23                     cin >> maze[i][j];24                 }25             }26             memset( dp , 0 , sizeof(dp) );27             dp[1][1] = 1;28             for( int i = 1 ; i<=n ; i++ )29             {30                 for( int j = 1 ; j<=m ; j++ )31                 {32                     for( int p = 0 ; p<=maze[i][j] ; p++ )33                     {34                         for( int q = 0 ; p+q<=maze[i][j] ; q++ )35                         {36                             if( !(p+q) || p+i>n || q+j >m )37                                 continue;38                             else39                             {40                                 dp[i+p][j+q] += dp[i][j];41                                 if( dp[i+p][j+q]>=mod )42                                     dp[i+p][j+q] %= mod;43                             }44                         }45                     }46                 }47             }48             cout << dp[n][m] <<endl;49         }50     }51     return 0;52 }
View Code

其实我觉得 刚接触dfs的时候 并不是那么容易理解 或者 像我这种迟钝点的 我写了下面一段小小的代码 有助于理解=-=

#include <iostream>using namespace std;void dfs( char ch,int x ){    char zh = ch + 1;    x+=2;    for( int i = x ; i<=10 ; i+=2 )    {        cout << ch << " " << i << endl;        dfs(zh,i);    }}int main(){    dfs(a,1);}
View Code

 

 

today:

  在虎扑看到了个很有感触的帖子...选了里面一些jr的回帖 当做today:

  和前女友异地恋,她经常主动打电话给我,有一天我嫌烦了,就对她说以后没事少给我打电话。她委屈地对我说:“想到你一个人在外地工作,身边一个朋友都没有,一个人吃饭,住房,我就很心疼,所以才老打电话给你。“

      和她分手快半年了,刚收到她的短信,想到和她过往,泪流满面
 
  在一起的那天:“哪怕你一辈子是小职员,我也会和你走下去。”
  分手的那天:“我觉得我十年后肯定不是这样,但是你十年后还是现在这个样子。”
  每天一点点努力,就是不想让下一个女人再说这种话。
 
  我不喜欢你抽烟,抽烟对身体不好又臭,如果你真的忍不住想抽烟的话就亲我。”现在想起,一幕幕仿佛昨天~~现在,只能祝她幸福了。
 
大一在网吧:
她:“在网吧?有件事想和你说。”
我:“现在没空,晚上回你。“
大二在宿舍:
她:“在睡觉呢?今天没点名,不过明天早上上课把你的看电影带过来给我看看好吗?”
我:“哦,明天有课?”
第二天继续睡觉。。。
大三夜里失眠:
我短信:“我还有机会吗?”
她回复:“黄花菜都凉了!”
毕业一年:
她:“我下月结婚,你能来吗?”
我:“这几个月在外派啊,估计赶不回来。”
毕业两年:
她:“帮我给宝宝取个名字吧,男孩。”
我:“哈,读书少,不会取啊。大宝?”
她:“你个弱智,永远不上心。”
啪,挂掉。




大哥们,我承认我当初比较混蛋,更多的是她是女神,我是穷小子,想得多,自卑。当黄花菜凉的时候人家就已经有男朋友了,你们想让我怎么办,去挖墙脚吗?我一直知道自己辜负了她,所以更不想去打扰她的生活,至于之后的交流也更多的是朋友之间的互动。
另外,当初有点文艺,快临产的时候她知道是个男孩,名字一直定不下来,所以问了下我,真没有其他的意思。
也奉劝JRS,凡事往前看,有好女孩要大胆追、要珍惜。记事起就哭过有数的四次,黄花菜就是其中之一!
 
我去找你。异地恋(不远),她几乎每个礼拜五都跟我说这句话,分手一年多我还是很难过的。
 
和前女友一起逛超市 她看到一盒巧克力很想买 拿起来又放下 
纠结了一会儿 最后说:算了不买了 好几十块钱 能给你买好多鸡翅吃呢。。。
现在想起来这句话还是很心酸 
最后也没有和她走到一起 还伤害了她 我真他妈是畜生