博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU1664 BFS + 数论 + 剪枝
阅读量:6812 次
发布时间:2019-06-26

本文共 2276 字,大约阅读时间需要 7 分钟。

  题目链接: , 一道比较蛋疼的搜索题。

  这道题有很多坑点,一点处理不好就要TLE。

 


 

  题意很简单,就是找到一个n的倍数m,要求m里包含的不同数字最少。

  做这道题要有数论的知识:对于任意的整数n,必然存在一个由不多于两个的数来组成的一个倍数。

  所以这里就比较好入手了,就是先搜一个数的情况,没找到的话再搜两个数的情况。

具体解法:

  用BFS来搜索,注意要有两个剪枝:如果当前队列里的结点的字符串的长度要比已经得到的结果的最小长度要长,则退出这次搜索;只有搜到的结点的数模n的余数未出现过,该节点才能入队,不然的话就会造成重复。还有不能在结点里直接保存字符串,所以要用一个前向指针来标记,需要得到字符串的时候进行一遍递归即可。

  用一个结构体来保存结点信息:当前结点模n的余数、前向指针、结点的字符、到该结点的字符串长度。由于数据量比较大,所以要自己手动维护一个队列。

  还有要注意的是,用string生成字符串的时候,ans = c + ans要比ans += c慢很多。

 

#include 
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int maxn = 65536 + 5;bool vis[maxn];int MinLen , n , a[5];struct Node { char ch; int mod , len , pre; //余数 , 当前长度 , 前指针} u , v , que[maxn]; string ans , curans;void GetStr(int k) { //用递归来得到字符串信息,注意这里的写法 if(k == -1) return; GetStr(que[k].pre); curans += que[k].ch;}bool cmp(string a , string b) { //比较两个串表示的十进制的大小 if(a.size() > b.size()) return true; if(a.size() == b.size() && a > b) return true; return false;}bool bfs(int k){ memset(vis , 0 , sizeof(vis)); int head = 0 , tail = -1; //队列的首尾指针 for(int i = 1 ; i <= k ; i++) { if(a[i] != 0) { //这里是保证第一个数字不为0 u.pre = -1; u.ch = a[i] + '0'; u.mod = a[i] % n; u.len = 1; vis[u.mod] = 1; que[++tail] = u; } } while(head <= tail) { u = que[head]; if(u.len > MinLen) break; //这里有一个剪枝 for(int i = 1 ; i <= k ; i++) { v.mod = (u.mod * 10 + a[i]) % n; v.ch = a[i] + '0'; v.len = u.len + 1; v.pre = head; if(!vis[v.mod]) { //同余判重 que[++tail] = v; vis[v.mod] = 1; if(v.mod == 0) { //搜到了结果 curans = ""; GetStr(tail); //获得字符串 return true; } } } head++; } return false;}int main(){ while(~scanf("%d" , &n) && n) { if(n <= 11) { cout << n << endl; continue; } bool flag = false; MinLen = maxn; ans = ""; for(int i = 1 ; i <= 9 ; i++) { a[1] = i; if(bfs(1)) { if(!flag || cmp(ans , curans)) { flag = true; ans = curans; MinLen = ans.size(); } } } if(flag) { cout << ans << endl; continue; } for(int i = 0 ; i <= 9 ; i++) { for(int j = i + 1 ; j <= 9 ; j++) { a[1] = i; a[2] = j; if(bfs(2)) { if(!flag || cmp(ans , curans)) { flag = true; ans = curans; MinLen = ans.size(); } } } } cout << ans << endl; } return 0;}

 

转载于:https://www.cnblogs.com/H-Vking/p/4508179.html

你可能感兴趣的文章
CentOS 6.9永久设置静态路由表以及路由表常用设置
查看>>
解决Docker时区与主机时区不一致的问题
查看>>
思考与知识
查看>>
访问日志不记录静态文件 访问日志切割 静态元素过期时间
查看>>
idea中复制module和module中的蓝色tag出现的方法
查看>>
python中的面相对象
查看>>
Spring缓存注解@Cache使用
查看>>
去除wordpress的category各方法对比
查看>>
traceroute
查看>>
精通汇编语言,有兴趣一起搞破解的请进!
查看>>
C#缺省参数可以让代码变得更加简洁明了与时俱进心里敞亮了很多了
查看>>
【自然框架】js版的QuickPager分页控件 V2.0
查看>>
poj-2049 Finding Nemo *
查看>>
模块化编程本质探讨
查看>>
利用博客与视频分享和交流知识和经验
查看>>
js操作dom对象
查看>>
Windows2003服务器安全配置:先关闭不需要的端口(转自)
查看>>
HDU1247 Hat’s Words 【trie树】
查看>>
iOS开发--动画篇之layout动画深入
查看>>
WorldWind源码剖析系列:视景体类Frustum
查看>>