zoukankan      html  css  js  c++  java
  • Find a Number (记忆化+BFS)

    题目来自“2018-2019 ICPC, NEERC, Southern Subregional Contest”,codeforces上放置了此题:Find a Number

    题意:给出两个正整数d,s。找到一个最小的数 n 使得 n%d==0,并且所有的 n 所有位的数字相加和为s。

    解题思路:常规想法,BFS搜索,从根节点0开始搜索,逐渐往尾部添加元素,显然会超时。

    优化:减少搜索的次数,减枝。BFS的搜索策略已经保证了第一个访问到的且满足条件的数 n 一定是最小值。因此更关心如何减枝,我们定义一个二维布尔类型数组 vis[d][s],其中 vis[i][j] 表示一个数 x、x%d==i、x的所有位上的数字和为 j 是否被找到了。如果找到了,说明我们不需要继续搜索。

    比如 d = 4,s=11,假如我们搜索到36的时候令 vis[0][9]=1 (因为实际上搜索到56就找到答案了), 后面再搜到某个数 x 满足和36一样的条件余数为0,和为9的数字我们都不会加入队列继续搜索,因为 x 的子空间有数满足最终要求,那么 36 的子树也一定包含答案,因为在这个题目里面36和 x 已经没有任何区别,它们的子树除了实际的数值不同外,余数以及每位上的和都相同。并且根据BFS的顺序,36的子树上的答案一定比 x 的子树上的答案小(仔细想想是不是这样~),它通过记录当前的状况是否访问过,从而判断是否要继续搜索

    比如下图。

    python代码

    #此代码直接放到cf上会超时,这应该是用python的原因导致的,改成C++应该就好了。
    #
    vis = [[0]*5050 for i in range(505)] q = [] #(int(n)%d, number_sum, n:str) d,s = 0,0 q.append((0,0,'')) vis[0][0]=1 z = input() a = z.split(' ') d = int(a[0]) s = int(a[1]) def bfs(): cs = [str(i) for i in range(10)] while q: now = q[0] q.pop(0) for i,j in enumerate(cs): nxt_mod = (now[0]*10+i)%d nxt_sum = now[1]+i nxt_n = now[2]+j if nxt_mod==0 and nxt_sum==s: return nxt_n if not vis[nxt_mod][nxt_sum] and nxt_sum<=s: q.append((nxt_mod,nxt_sum,nxt_n)) vis[nxt_mod][nxt_sum]=1 return -1 print(bfs())
  • 相关阅读:
    作用域 + this指向 的一道没面试题
    找出数组中最大的值
    统计数组中每个值出现的次数, 统计对象中每个字符出现的次数
    uniapp在h5 和 APP 端兼容性 bug 解决方案
    数组去重的常用方法,利用Promise实现函数按序执行
    momentjs实现距离当前时长并且回现中文效果
    SQL server 上机练习题
    JS 9
    JS 8
    JS 7
  • 原文地址:https://www.cnblogs.com/ISGuXing/p/14809748.html
Copyright © 2011-2022 走看看