• 快速加法(C++)[DFS]


    题目:

    Description

    小小秦是小秦的弟弟,他才学会加法。

    小秦现在想考试一下弟弟对加法的掌握程度,但他又不想出平时学校老师出的那些题

    于是他给出一串数字S,再给出一个整数N。

    问弟弟这样一个问题 在S中添加几个加号,可以使得表达式的结果为S。

    例如 S="303",N=6 则只最少只要一个加号就可以了即3+03=6

    S="1110",N=3 则最少要加3个加号,即1+1+1+0=3

    Format

    Input

    第1行:1个字符串S(1 ≤ S的长度 ≤ 40) 和1个整数N(N≤100000)。

    S和N用1个空格分隔。

    Output

    第1行:1个整数K,表示最少的加法次数让S等于N。

    如果怎么做都不能让S等于N,则输出-1。

    Samples

    【输入样例】

    输入数据 1

    99999 45
    

    输出数据 1

    4

     思路:

    这道题采用DFS(深度优先)算法。

    我们可以模拟添加加号的位置:

    Dep指向当前数, 

    记下当前的累加和SumSum并不一定加到Dep的深度),

    再记下当前的加数NowNum

    和加号的个数Jia(拼音大法)

    注意,关于NowNum有两种操作:

    1.NowNum是会延长的,它可以与当前Dep指向的数合并,但不会累加,不然会很麻烦,因为有Sum记下累加和就够了。如:当前NowNum=99,当前Dep指向数字9,则NowNum可以与1合并为999

    2.NowNum加到Sum里更新累加和,此时NowNum变成Dep指向的数,此时加号个数也要加一

     我们做就可以按这两种操作来做 01DFS

    TLE代码:

    1. #include
    2. using namespace std;
    3. const int N= 210;
    4. string s;
    5. int len;
    6. int m;
    7. int ans=INT_MAX;//答案
    8. int zhuan(char ss) {//转换器,将字符型转成整型
    9. if(ss=='0') return 0;
    10. if(ss=='1') return 1;
    11. if(ss=='2') return 2;
    12. if(ss=='3') return 3;
    13. if(ss=='4') return 4;
    14. if(ss=='5') return 5;
    15. if(ss=='6') return 6;
    16. if(ss=='7') return 7;
    17. if(ss=='8') return 8;
    18. if(ss=='9') return 9;
    19. }
    20. void dfs(int dep,int sum,int jia,int now_num) {
    21. if(sum>m) return ;//如果sum比要求的和m还大,可以return了
    22. if(dep==len) {//如果已经遍历完这串数
    23. if(sum+now_num==m) //且sum为要求的和m
    24. ans=min(jia,ans);//更新答案
    25. return ;//一定要return
    26. }
    27. // 01DFS:
    28. dfs(dep+1,sum,jia,now_num*10+zhuan(s[dep]));
    29. //now_num它可以与当前dep指向的数合并
    30. dfs(dep+1,sum+now_num,jia+1,zhuan(s[dep]));
    31. //也可以把now_num加到sum中,此时jia+1
    32. }
    33. int main() {
    34. cin>>s>>m;
    35. len=s.size();//获取长度
    36. dfs(0,0,0,0);
    37. if(ans==INT_MAX) puts("-1");
    38. else
    39. cout<
    40. return 0;
    41. }

    对,你没有看错,TLE了,这说明没完

    于是我又加了几个剪枝:

     正解:

    1. #include
    2. using namespace std;
    3. const int N = 210, M = 100010;
    4. string s;
    5. int len;
    6. int m;
    7. int ans = INT_MAX;
    8. int bs[N];
    9. /* 可行性剪枝
    10. bs[i]代表把数字串中每一个数单独加起来(不合并)加到第i位 (类似前缀和)
    11. 此是1~i贡献的值最小
    12. 如一列数1、2、3、4、5
    13. 则bs[3]=1+2+3+4=10; */
    14. int ss[M];
    15. /* 最优性剪枝
    16. ss[i]代表凑出i要花费的最少的加号数量(i是累加和,相当于DFS中的sum) */
    17. int zhuan (char ss)
    18. {
    19. if (ss == '0') return 0;
    20. if (ss == '1') return 1;
    21. if (ss == '2') return 2;
    22. if (ss == '3') return 3;
    23. if (ss == '4') return 4;
    24. if (ss == '5') return 5;
    25. if (ss == '6') return 6;
    26. if (ss == '7') return 7;
    27. if (ss == '8') return 8;
    28. if (ss == '9') return 9;
    29. }
    30. void dfs (int dep, int sum, int jia, int now_num)
    31. {
    32. if (sum > m) return ;
    33. if (now_num + sum > m) return ;
    34. if (dep == len)
    35. {
    36. if (sum + now_num == m) ans = min (jia, ans);
    37. return ;
    38. }
    39. if (sum + bs[len - 1] - bs[dep] > m) return ;
    40. //如果把dep到末位的数一个个加起来都大于m的话就return吧
    41. if (ss[sum])//如果不是最优的,return;
    42. if (ss[sum] < jia) return ;
    43. ss[sum] = jia;//否则更新最优的
    44. dfs (dep + 1, sum, jia, now_num * 10 + zhuan (s[dep]) );
    45. dfs (dep + 1, sum + now_num, jia + 1, zhuan (s[dep]) );
    46. }
    47. int main()
    48. {
    49. cin >> s >> m;
    50. len = s.size();
    51. bs[0] = zhuan (s[0]);
    52. for (int i = 1; i < len; i++)//做前缀和
    53. bs[i] = bs[i - 1] + zhuan (s[i]);
    54. dfs (0, 0, 0, 0);
    55. if (ans == INT_MAX) puts ("-1");
    56. else
    57. cout << ans << endl;
    58. return 0;
    59. }

  • 相关阅读:
    JetpackCompose从入门到实战学习笔记3——Text的简单使用
    2022/6/27 Quartz(定时任务)讲解+入门案例
    封装一个websocket,支持断网重连、心跳检测,拿来开箱即用
    Packet Tracer - 配置多区域 OSPFv2
    VS Code插件 — Settings Sync : 设置和同步用户配置
    人工智能基础部分21-神经网络中优化器算法的详细介绍,配套详细公式
    昨日阅读量898
    开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    【LeetCode】232.用栈实现队列
    正点原子嵌入式linux驱动开发——Linux SPI驱动
  • 原文地址:https://blog.csdn.net/ytk888/article/details/125982850