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;
}