首页 > 其他分享 >数字替换

数字替换

时间:2023-03-04 22:33:20浏览次数:45  
标签:剪枝 遍历 数字 int DFS 位数 ans 替换

题目内容

给定两个整数 n,x

你可以对 x 进行任意次以下操作:

  • 选择 x 的一位数字 y,将 x 替换为 x×y。

请你计算通过使用上述操作,将 x 变为一个 n 位数字(不含前导 00),所需要的最少操作次数。

例如,当 n=3,x=2 时,对 2 进行如下 4 次操作,即可使其变为 3 位数字:

  1. 将 2 替换为 2×2=4
  2. 将 4 替换为 4×4=16。
  3. 将 16 替换为 16×6=96
  4. 将 96 替换为 96×9=864      

输入格式

共一行,包含两个整数 n,x

输出格式

一个整数,表示将 x 变为一个 n 位数字,所需要的最少操作次数。

如果无解,则输出 -1

数据范围

所有测试点满足 2≤n≤19,1≤x<10^n-1

输入样例3:

13 42

输出样例3:

12

思路:这一题不能采用贪心的算法来求解,贪心的话13 42 的测试样例的结果是13,和正确结果不同。
因为可能每一次不乘x中最大的位数值。本题我们采用DFS(好剪枝),不采用(BFS),如果采用BFS
有效的位数是2-9,0和1是无效的。有效的数是8个。如果采用BFS,时间复杂度就是8^n。所以我们
采用DFS,DFS可以有效剪枝.
本题的DFS有两处需要注意的地方
1.DFS遍历的数从高到低进行遍历,依次遍历9-2
2.剪枝,当 当前数据的操作数 + (n-当前数据的位数) >= 返回的位数值就直接return。因为 每次
操作最多能让当前数据的位数+1,n-当前的位数,能让我们大致推出当前数据到达n位大概还有几次
操作空间,加上当前数据的操作数就是总的操作数,总的操作数,如果比之前求的值大,就直接剪枝。

代码块
 1 //BFS(剪枝)
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 //INF表示的是遍历的最大次数
 5 int n;
 6 const int INF = 1000;
 7 int ans = INF;
 8 //x是传入的数值,res是x对应的操作数
 9 void dfs(long long x, int d){
10     //表示x中出现的元素,后面DFS需要直到x中出现的元素值
11     bool st[10] = {0} ;
12     //获取x的位数
13     int cnt = 0;
14     for(long long y = x; y; y /= 10){
15         cnt++;
16         //表示x中 xx % 10 的数值有在位数中出现过
17         st[y%10] = true;
18     }
19     //剪枝,如果当前的操作数 + (元素的位数(n) - 元素当前的位数(cnt) ) >= ans 的话,就可以不用遍历了
20     if(d + n - cnt >= ans) return ;
21     //如果当前的位数和n相同,改变ans的值
22     if(cnt == n){
23         ans = d; 
24         return;
25     } 
26     //DFS,DFS从大的数值往小的数值进行遍历
27     for(int i = 9; i >= 2; i--){
28         //如果该数在x的位数的数值中有出现就遍历
29         if(st[i]) 
30             dfs(x*i,d+1);
31     }
32 }
33 int main() {
34     long long x;
35     cin >> n >> x;
36     dfs(x,0);
37     //如果无解,将rr变成-1
38     if(ans == INF) ans = -1;
39     cout << ans << endl;
40     return 0;
41 }

 

题目来源 4868. 数字替换 - AcWing题库
题解思路来源个人空间 - AcWing

标签:剪枝,遍历,数字,int,DFS,位数,ans,替换
From: https://www.cnblogs.com/kgx213/p/17179382.html

相关文章