zoukankan      html  css  js  c++  java
  • 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             else
    27             {
    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             else
    29             {
    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                             else
    39                             {
    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,凡事往前看,有好女孩要大胆追、要珍惜。记事起就哭过有数的四次,黄花菜就是其中之一!
     
    我去找你。异地恋(不远),她几乎每个礼拜五都跟我说这句话,分手一年多我还是很难过的。
     
    和前女友一起逛超市 她看到一盒巧克力很想买 拿起来又放下 
    纠结了一会儿 最后说:算了不买了 好几十块钱 能给你买好多鸡翅吃呢。。。
    现在想起来这句话还是很心酸 
    最后也没有和她走到一起 还伤害了她 我真他妈是畜生
     
    just follow your heart
  • 相关阅读:
    [DB] 数据库的连接
    JS leetcode 翻转字符串里的单词 题解分析
    JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
    JS leetcode 搜索插入位置 题解分析
    JS leetcode 杨辉三角Ⅱ 题解分析
    JS leetcode 寻找数组的中心索引 题解分析
    JS leetcode 移除元素 题解分析
    JS leetcode 最大连续1的个数 题解分析
    JS leetcode 两数之和 II
    JS leetcode 反转字符串 题解分析
  • 原文地址:https://www.cnblogs.com/radical/p/3897412.html
Copyright © 2011-2022 走看看