题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1664 , 一道比较蛋疼的搜索题。

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


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

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

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

具体解法:

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

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

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

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

HDU1664 BFS + 数论 + 剪枝的更多相关文章

  1. UVA - 11882 Biggest Number(dfs+bfs+强剪枝)

    题目大意:给出一个方格矩阵,矩阵中有数字0~9,任选一个格子为起点,将走过的数字连起来构成一个数,找出最大的那个数,每个格子只能走一次. 题目分析:DFS.剪枝方案:在当前的处境下,找出所有还能到达的 ...

  2. hdu1664 bfs+余数判重

    input n 不超过50个例子,n==0结束输入 Sample Input 7 15 16 101 0 output 最少个不同数字的n的倍数的x,若不同数字个数一样,输出最小的x Sample O ...

  3. soj1091 指环王 bfs+hash+剪枝

    原题链接http://acm.scu.edu.cn/soj/problem.action?id=1091 这题的主要解法就是搜索,我用的是bfs,用map将二维数组处理成字符串作为主键,到达当前状态的 ...

  4. POJ 3278 Catch That Cow[BFS+队列+剪枝]

    第一篇博客,格式惨不忍睹.首先感谢一下鼓励我写博客的大佬@Titordong其次就是感谢一群大佬激励我不断前行@Chunibyo@Tiancfq因为室友tanty强烈要求出现,附上他的名字. Catc ...

  5. hdu 1044(bfs+dfs+剪枝)

    Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  6. hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)

    题目传送门 题目大意:给出n座城市,每个城市都有一个0到9的val,城市的编号是从0到n-1,从i位置出发,只能走到(i*i+1)%n这个位置,从任意起点开始,每走一步都会得到一个数字,走n-1步,会 ...

  7. HDU1495 非常可乐(BFS/数论)

    大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多.但see ...

  8. hdu 2717 Catch That Cow(BFS,剪枝)

    题目 #include<stdio.h> #include<string.h> #include<queue> #include<algorithm> ...

  9. UVA-11882 bfs + dfs + 剪枝

    假设当前已经到达(x,y),用bfs判断一下还可以到达的点有maxd个,如果maxd加上当前已经经过的长度小于当前答案的长度就退出,如果相同,就将bfs搜索到的点从大到小排序,如果连最大序列都无法大于 ...

随机推荐

  1. .NET 中文件嵌套,例如:cshtml文件下面嵌套css和js【机器翻译】

    越来越多的我发现自己在我的一些较大的Web项目中丢失了文件.有很多内容要处理 - HTML视图,几个派生CSS页面,页面级CSS,脚本库,应用程序范围的脚本和页面特定的脚本文件等等.幸运的是,我使用R ...

  2. Postman使用-2

    转载:https://www.cnblogs.com/yunman/p/7884537.html Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件. 接口请求流程 一.g ...

  3. ASP.NET MVC 小牛之旅2:体验第一个MVC程序

    了解了什么是MVC之后,接下来用一个非常简单的留言板程序概要的了解MVC网站开发的过程,对MVC开发有个大致的轮廓.第一个项目将不会提到过多与数据库相关的技术,因此将以Framework Code F ...

  4. pyMongo 一些基本操作

    1. find() 函数, 可以在函数体内直接指定 filter, sort, projection(限制field), 语法如下: datas = col.find( filter = {" ...

  5. 51nod1347(简单逻辑)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1347 题意:中文题诶- 思路:稍推理一下就可以发现字符串a是 ...

  6. 2017-10-19 NOIP模拟赛

    Count(哈格朗日插值) 题解: 有个定理,另sum(x)表示小于等于x的数中与x互质的数的和 sum(x)=φ(x)*x/2    最后可知f(x)=x  (f(1)=2)  当然打表能知道. 然 ...

  7. jzoj3208. 【JSOI2013】编程作业(kmp)

    题面 Description Will相信,很多同学都有过这样的经历:大牛已经写好了编程作业,而作为菜鸟的自己不会写怎么办呢?拿大牛的代码抄一下嘛!但是提交一模一样的作业是不是不太好?于是就改一改变量 ...

  8. POST和 GET

    http GET 和 POST 请求的优缺点.区别以及误区     Get和Post在面试中一般都会问到,一般的区别: (1)post更安全(不会作为url的一部分,不会被缓存.保存在服务器日志.以及 ...

  9. RABC(Role-Based Access Control) 基于角色的权限访问控制

    基于角色的权限访问控制(Role-Based Access Control),通过角色绑定权限,然后给用户划分角色.在web应用中,可以将权限理解为url,一个权限对应一个url. 使用thinkph ...

  10. [Cqoi2014]危桥 (两遍网络流)

    题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { , ...