poj1465Multiple(经典BFS+余数判重)

Multiple

Time Limit: 1000MS   Memory Limit: 32768K
Total Submissions: 6936   Accepted: 1495

Description

a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM (at least one), finds the smallest strictly positive multiple of N that has no other digits besides X1,X2..XM (if such a multiple exists).

Input

The input has several data sets separated by an empty line, each data set having the following format:

On the first line - the number N

On the second line - the number M

On the following M lines - the digits X1,X2..XM.

Output

For each data set, the program should write to standard output on a single line the multiple, if such a multiple exists, and 0 otherwise.

An example of input and output:

Sample Input

22
3
7
0
1

2
1
1

Sample Output

110
0

Source

Southeastern Europe 2000

这道题由于数据的规模,在优化上有一个很好的剪枝,会节省下不少内存和时间,就是余数判重,这个优化在别人的题解里肯定说的很多我就不再多嘴了,其次再说这个BFS,在宽搜之前要对m个数从小到大排一下序,因为题目要求是要最小的倍数,这样你要确定当你向上找到那个父节点的时候,他比之后的数都是小的-
-

最后,把得到的答案放在数组里,因为你是从最小的地方开始放的,所以输出的时候从低位到高位,要倒序输出

<( ̄ˇ ̄)/我要好好做题,好好写题解^_^

这是代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int num[12];
int n,m;
int flag[5200];
char answer[5200];
struct node{
     int fid;
     int num;
     int mod;
}tree[5200];

queue<int>qq;

void bfs(){
     if(!n){
          cout<<0<<endl;
          return;
     }
     int idx=1;
     while(!qq.empty()) qq.pop();
     memset(flag,0,sizeof(flag));
     for(int i=1;i<=m;++i){
          int nm=num[i];
          int mod=nm%n;
          if(!num[i]){        //若当前这个数是0,跳过
               continue;
          }
          if(!mod){      //若当前这个数对n取余为0,说明这个数是n的倍数,直接输出这个数然后返回
               cout<<nm<<endl;
               return;
          }
          if(!flag[mod]){          //若这个数对n取余的余数以前没有取到过(余数判重) 将这个数加入到树中,将这个数的位置进入队列
               flag[mod]=1;
               tree[idx].fid=0;
               tree[idx].num=nm;
               tree[idx].mod=mod;
               qq.push(idx++);
          }
     }

     while(!qq.empty())       //广搜
     {
          int ff=qq.front();
          qq.pop();
          int md=tree[ff].mod;
          for(int i=1;i<=m;++i)
          {
               int nm=num[i];
               int addnum=md*10+nm;
               int addmod=addnum%n;

               if(!addmod){        //如果这个数和m个数中的一个组合是n的倍数
                    int k=0;
                    answer[k++]=nm+'0';
                    answer[k++]=tree[ff].num+'0';
                    while(tree[ff].fid)      //寻找此点的父节点
                    {
                         ff=tree[ff].fid;
                         answer[k++]=tree[ff].num+'0';
                    }
                    for(int kk=k-1;kk>=0;kk--)
                         printf("%c",answer[kk]);
                    printf("\n");
                    return;
               }
               if(!flag[addmod])        //如果当前次的数的组合的余数不为零且未出现过,加入队列
               {
                    flag[addmod]=1;
                    tree[idx].fid=ff;
                    tree[idx].num=nm;
                    tree[idx].mod=addmod;
                    qq.push(idx++);
               }
          }
     }
     cout<<0<<endl;
     return;
}

int main()
{
     while(scanf("%d%d",&n,&m)!=EOF)
     {
          for(int i=1;i<=m;++i)
               scanf("%d",&num[i]);
          sort(num+1,num+m+1);
          bfs();
     }
     return 0;
}
时间: 2024-07-30 11:24:14

poj1465Multiple(经典BFS+余数判重)的相关文章

HDU 4474&amp;&amp;POJ 1465 BFS&amp;&amp;余数判重

两道题只是输入输出格式略有不同 给出n,m,m个数 要求生成一个数x,是n的倍数,并且只由这M个数构成(或不能含有这M个数中的任意一个),求最小的x,没有则输出-1(0): BFS找每一个满足n的倍数的数,用余数判重优化 对于给定两个数A,B,如果A和B模N都相同,设为C,即: A=x*N+C B=y*N+C 那么如果在A后面加上一个数字能够被N整除,则在B后面加上这个数字也肯定可以被N整除 即:(A*10+X)%N==(B*10+X)%N 因此可以利用模N的结果进行判重,只保留相同余数的最小数

[bfs+余数判重+路径记录] hdu 4474 Yet Another Multiple Problem

题意: 给一个n和m个数字(一位数) 求最小的n的倍数不含有这m个数字,不存在输出-1 思路: 首先有可能这个数超long long 所以无法暴力解决 所以这题应该是一个bfs 为什么能用余数判重呢 对于当前的余数进到队列里,一定是这个余数对应数的最小值 接下来再怎么添加到满足条件的后续东西应该是一样的 所以就可以余数判重了,类似数位dp的记录方式 然后再加上一个路径记录就好了 代码: #include"cstdlib" #include"cstdio" #incl

HDU 2579 Dating with girls(2) BFS 余数判重

对于石头的处理就按照每个位置的时间取k的余数判一下重复就好,其他随意写 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue> #include <deque> #include

11198 - Dancing Digits(BFS + hash判重)

题目:11198 - Dancing Digits 题目大意:每组数据给出8个数字,可能正可能负.要求最后将这8个数字按照数字绝对值从小到大的排序.排序的规则是让某个数字a邀请另一个数字b跳舞,这样a就可以插到b的左边或是右边,a能邀请b跳舞,则a* b <0 ,且a+b要是素数.题目问给出一组数据问能否通过邀请跳舞来排序,能的话就输出最少的邀请次数,否则输出-1. 解题思路:这题一开始竟然想着dfs,但是后面发现,这样的判断树可以是无限大,因为可以a邀请完b,然后b在邀请a,这样一来一回有可能

Keyboarding (bfs+预处理+判重优化)

# #10030. 「一本通 1.4 练习 2」Keyboarding [题目描述] 给定一个 $r$ 行 $c$ 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 $5$ 个控制键,你可以移动电视屏幕上的光标来打印文本.一开始,光标在键盘的左上角,每次按方向键,光标总是跳到下一个在该方向上与当前位置不同的字符,若不存在则不移动.每次按选择键,则将光标所在位置的字符打印出来. 现在求打印给定文本(要在结尾打印换行符)的最少按键次数. [算法] 1.预处理四个方向能到达的点.

Hdu2437-Jerboas(取余数判重搜索)

Jerboas are small desert-living animals, which resemble mice with a long tufted tail and very long hind legs. Jerboas shelter in well-hidden burrows. They create two types of burrow: temporary and permanent. The temporary burrows are plain tubes whil

poj 1465 &amp; zoj 1136 Multiple (BFS+余数重判)

Multiple Time Limit: 1000MS   Memory Limit: 32768K Total Submissions: 6177   Accepted: 1346 Description a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM (at least one), finds the small

八数码问题+路径寻找问题+bfs(隐式图的判重操作)

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6

BFS+Hash(储存,判重) HDOJ 1067 Gap

题目传送门 题意:一个图按照变成指定的图,问最少操作步数 分析:状态转移简单,主要是在图的存储以及判重问题,原来队列里装二维数组内存也可以,判重用神奇的hash技术 #include <bits/stdc++.h> using namespace std; const int MOD = 1e6 + 7; struct Point { int ch[5][9]; int x[4], y[4]; int step; }; bool vis[MOD]; int ha; int get_hash(i