题目链接: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. FreeSql 新功能介绍:贪婪加载五种方法

    前言 FreeSql 在经过6个月的开发和朋友们的工作实践,不断的改进创新,目前拥有1500个左右单元测试方法,且每个方法内又复盖不同的测试面. 今天介绍 FreeSql 各种贪婪加载的姿势,作下总结 ...

  2. 2017-10-12 NOIP模拟赛

      斐波那契 /* 相同颜色的节点与父亲节点的差相等,且是一个小于它的最大斐波那契数 所以降两个点同时减去小与它的最大斐波那契数,直到两点相等 */ #include<cstdio> ; ...

  3. [USACO1.4]等差数列 Arithmetic Progressions

    题目描述 一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列. 在这个问题中a是一个非负的整数,b是正整数.写一个程序来找出在双平方数集合(双 ...

  4. POJ1021 2D-Nim

    题目来源:http://poj.org/problem?id=1021 题目大意: 有一种在棋盘上玩的游戏,每一步,一个玩家可以从棋盘上拿走连续行或列的棋子.谁拿到最后一颗棋子就胜利.如下图所示的棋盘 ...

  5. LeetCode 230 Kth Smallest Element in a BST 二叉搜索树中的第K个元素

    1.非递归解法 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * ...

  6. 【Unity3D】Unity中用C#读取CSV文件

    1.创建csv文件 既然做实验嘛,没有资源怎么行,自己徒手写个csv文件吧,打开Numbers工具,新建一个表格文件,我的文件编辑截图如下: 创建完成后,导出成csv格式,我这里文件名为test.cs ...

  7. CentOS安装MySQL,(常规安装方式MySQL无法远程连接)

    转载自:https://blog.csdn.net/z13615480737/article/details/78906598 CentOS7默认数据库是mariadb, 但是 好多用的都是mysql ...

  8. 设计模式--观察者模式(KVO)

    观察者模式(Observer):观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 举个例子, ...

  9. D2 前端会议

    D2 前端会议 时间 2019年1月6日 图片

  10. Windows、Unix、Mac不同操作系统的换行问题-剖析回车符\r和换行符\n

    转载链接:http://blog.csdn.net/tskyfree/article/details/8121951 一.概念: 换行符‘\n’和回车符‘\r’ (1)换行符就是另起一行  --- ' ...