1002.Shortest path
签到题 记忆化搜索
题目大意
给定一个正整数 n n n ,可以对其进行以下操作:
- 如果 n n n 能被 3 3 3 整除,则可以使 n = n / 3 n=n/3 n=n/3 ;
- 如果 n n n 能被 2 2 2 整除,则可以使 n = n / 2 n=n/2 n=n/2 ;
- 使 n = n − 1 n=n-1 n=n−1
求使得 n n n 变成 1 1 1 的最少操作次数
解题思路
将样例Output输出即可
这题不难,但确实精彩()//毕竟……
《钉耙编程”中国大学生算法设计超级联赛》是由hdu自主研发的一款全新开放世界冒险竞赛。竞赛发生在一个被称作“hdu”的幻想世界,在这里,被编译器选中的人将被授予“C++”,导引代码之力。你将扮演一位名为“acmer”的神秘角色,在自由的打题中邂逅性格各异能力独特的STL容器,和他们一起击败强题,找回AC的代码
不闹了,解题吧()
不难看出操作  
     
      
       
       
         3 
        
       
      
        3 
       
      
    3 的收益最低,是不满足操作  
     
      
       
       
         1 
        
       
         , 
        
       
         2 
        
       
      
        1,2 
       
      
    1,2 的时候凑条件用的。
 而由于只允许整除,操作  
     
      
       
       
         1 
        
       
         , 
        
       
         2 
        
       
      
        1,2 
       
      
    1,2 的优劣性不好评估(因为要夹杂操作  
     
      
       
       
         3 
        
       
      
        3 
       
      
    3 而不单纯是减少的量的区别),因此每次对本次进行的两种操作方案进行比较。
按以下操作递归处理 n n n :
- 如果 n = 1 n=1 n=1 ,则返回 0 0 0 ;
- 进行若干次(可能0次)操作 3 3 3 使得 n n n 能被 2 2 2 整除,执行操作 2 2 2
- 进行若干次(可能0次)操作 3 3 3 使得 n n n 能被 3 3 3 整除,执行操作 1 1 1
由于数据范围的关系,传统的DFS会超时,因此需要使用记忆化搜索
 即每次计算完某个数(记为  
     
      
       
       
         x 
        
       
      
        x 
       
      
    x )的结果,将其保存下来,后续搜索  
     
      
       
       
         x 
        
       
      
        x 
       
      
    x 时就无需继续搜索到底部,直接输出这个数的结果即可
 记忆化搜索可以用 map 实现,频繁读取而不考虑元素顺序的可以使用 unordered_map ,有效降低时间空间复杂度

 下面两份使用了 map ,代码完全一致;上面一份仅仅将 map 改为了 unordered_map
时间复杂度
O ( t log  2 n ) O(t\log^2n) O(tlog2n)
参考代码
参考代码为已AC代码主干,其中部分功能需读者自行实现
unordered_map<ll,ll> mp;
ll dfs(ll n){
    if(n<=1) return 1-n;
    if(mp[n]) return mp[n];
    ll t1,t2;
    t1=n%2+1+dfs(n/2);
    t2=n%3+1+dfs(n/3);
    return mp[n]=min(t1,t2);
}
void solve()
{
    ll n;cin >> n;
    cout << dfs(n) << endl;
}



















