HDU 4474 Yet Another Multiple Problem(数位搜索+余数剪枝)
2013-10-27 18:08
816 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4474
题目大意:就是给你一个数 n ,然后给你 m 个digits ,问你 n 的倍数里各个数位不出现这 m 个数的最小是多少?
思路:这是 2012 成都现场赛的 K 题,今天下午做了一下,被这道题目虐成翔了,最后开挂 A 了这道题目。。 (所谓开挂,是指稍微瞄了下题解 = =)
原来是数位搜索,其实关键是用余数来剪枝这里,真想不到。。。 先把能出现的数压进队列,然后开始广搜,每个节点记录两个值,一个是当前余数 c,和到这个节点为止所选择的数,所谓用余数剪枝,就是指,如果当前选择了一个数,然后余数一算,发现之前的节点里出现过这个余数,就不压入队列,因为之前出现过,那么肯定是以之前的节点为起点找来得小,因为要么数字长度短,要么当前数字小,然后只要取出来一个 c == 0,那么就break,这样就找到了,就把这个 num 输出就好。因为余数最多 n,所以时间复杂度为O(n)。
由于我自己写代码里,为了方便,用 vector 来存至当前节点为止的所有的数字,中间有拷贝的过程,所以耗时比较多,最不耗时的应该是自己开队列,然后直接记录前缀,就这个数字是什么,前面是哪个节点,有 20S,反正不超时就好。。 = =
一看到这道题,第一想法肯定是枚举倍数暴力,我们先开始就这样做了,果然到了预期的效果,倍数多了TLE,少了WA,又想不好的方法,唉。。。不过话说回来,这道题还是很好的一道复旦风格的搜索题啊!
代码如下:
题目大意:就是给你一个数 n ,然后给你 m 个digits ,问你 n 的倍数里各个数位不出现这 m 个数的最小是多少?
思路:这是 2012 成都现场赛的 K 题,今天下午做了一下,被这道题目虐成翔了,最后开挂 A 了这道题目。。 (所谓开挂,是指稍微瞄了下题解 = =)
原来是数位搜索,其实关键是用余数来剪枝这里,真想不到。。。 先把能出现的数压进队列,然后开始广搜,每个节点记录两个值,一个是当前余数 c,和到这个节点为止所选择的数,所谓用余数剪枝,就是指,如果当前选择了一个数,然后余数一算,发现之前的节点里出现过这个余数,就不压入队列,因为之前出现过,那么肯定是以之前的节点为起点找来得小,因为要么数字长度短,要么当前数字小,然后只要取出来一个 c == 0,那么就break,这样就找到了,就把这个 num 输出就好。因为余数最多 n,所以时间复杂度为O(n)。
由于我自己写代码里,为了方便,用 vector 来存至当前节点为止的所有的数字,中间有拷贝的过程,所以耗时比较多,最不耗时的应该是自己开队列,然后直接记录前缀,就这个数字是什么,前面是哪个节点,有 20S,反正不超时就好。。 = =
一看到这道题,第一想法肯定是枚举倍数暴力,我们先开始就这样做了,果然到了预期的效果,倍数多了TLE,少了WA,又想不好的方法,唉。。。不过话说回来,这道题还是很好的一道复旦风格的搜索题啊!
代码如下:
#include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm> #define LL __int64 using namespace std; const int MAXN = 11111; struct Node { vector <int> num; int c; } tmp; queue <Node> q; int have[MAXN]; int vis[11]; int n; void bfs() { while(!q.empty()) q.pop(); memset(have,0,sizeof(have)); for(int i = 1;i < 10;i++) if(!vis[i]) { if(have[i%n]) continue; tmp.num.clear(); tmp.num.push_back(i); tmp.c = i%n; q.push(tmp); have[i%n] = 1; } while(!q.empty()) { Node cur = q.front(); if(cur.c == 0) break; q.pop(); for(int i = 0;i < 10;i++) { if(vis[i]) continue; int tt = (cur.c*10+i)%n; if(!have[tt]) { have[tt] = 1; tmp.num.clear(); for(int j = 0;j < cur.num.size();j++) tmp.num.push_back(cur.num[j]); tmp.num.push_back(i); tmp.c = tt; q.push(tmp); } } } if(!q.empty()) { for(int i = 0;i < q.front().num.size();i++) printf("%d",q.front().num[i]); puts(""); } else puts("-1"); } int main() { int m; int cas = 0; while(~scanf("%d%d",&n,&m)) { memset(vis,0,sizeof(vis)); for(int i = 0;i < m;i++) { int a; scanf("%d",&a); vis[a] = 1; } printf("Case %d: ",++cas); bfs(); } return 0; }
相关文章推荐
- hdu 4474 Yet Another Multiple Problem 模型转换 BFS搜索
- HDU 4474 Yet Another Multiple Problem(搜索 BFS)
- hdu 4474 Yet Another Multiple Problem 模型转换 BFS搜索 根据剩余类建图广搜
- 【搜索】 HDU 4474 Yet Another Multiple Problem
- HDU-4474 Yet Another Multiple Problem BFS搜索
- HDU 4474 Yet Another Multiple Problem 搜索
- HDU 4474 Yet Another Multiple Problem bfs枚举所有余数
- HDU 4474 Yet Another Multiple Problem ( BFS + 同余剪枝 )
- HDU5952 Counting Cliques 【搜索剪枝】
- HDOJ 4474 Yet Another Multiple Problem(BFS + 剪枝)
- 最短路 + 搜索 + 剪枝 之 hdu 4848 Wow! Such Conquering!
- HDU 4294 Multiple [搜索]
- 搜索专题(DFS&&BFS&&剪枝)HDU 1728-逃离迷宫
- HDU 5323 Solve this interesting problem(dfs结合线段树特点剪枝)
- HDU 1016 Prime Ring Problem DFS + 记忆化搜索
- hdu 4474 Yet Another Multiple Problem
- HDU 4282 A very hard mathematic problem [剪枝/二分]
- 搜索(剪枝优化):HDU 5113 Black And White
- HDU 3699 A hard Aoshu Problem (暴力搜索)
- HDU 5803 Zhu's Math Problem(数位DP)