Poj 1465 Multiple BFS+余数判重
题意:现在给你M个数字和另外一个数N(N<5000),问你能否用这M个数字中的一个或几个(可以重复)来构成一个数,使得这个数能被N整除,如果能输出最小的,不能输出0
显然可以将构成的数字位数作为层数来进行bfs,通过对给你的M个数进行排序,来保证最先出现的肯定是最小的。
关键问题是如何判重?
因为有两个数要是被N除之后余数相等,那么在这两个数后面添加相同个数字之后余数也必定相等
A = a*N+C
B = b*N+C
(A*10+k)%N = C*10+k%N=(B*10+k)%N
所以每个数作为前缀的时候一样的余数的只需要出现一次即可,就可以判重了。
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <set>
#include <map>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <string>
using namespace std;
int N,M,num[1000];
int val[5555],pre[5555];
int len[5555],res[5555];
bool tab[5555];
bool notzero(int id) {
return !(len[id] == 1 && val[id] == 0);
}
void print_path(int now) {
if(~pre[now]) print_path(pre[now]);
putchar(val[now] + '0');
}
int main() {
while(scanf("%d%d",&N,&M) != EOF) {
memset(tab,0,sizeof(tab));
for(int i = 0;i < M;i++) {
scanf("%d",&num[i]);
}
sort(num,num + M);
if(N == 0) {
puts("0"); continue;
}
int front = 0,rear = 0;
for(int i = 0;i < M;i++) {
len[rear] = 1;
res[rear] = num[i] % N;
pre[rear] = -1;
val[rear] = num[i];
rear++;
if(num[i] != 0) {
tab[num[i] % N] = true;
}
}
int ans = 0;
while(front < rear) {
int now = front; front++;
if(res[now] == 0 && notzero(now)) {
ans = now; break;
}
for(int i = 0;i < M;i++) {
if(!notzero(now) && num[i] == 0) continue;
int nres = (res[now] * 10 % N + num[i] % N) % N;
if(tab[nres] == false) {
tab[nres] = true;
len[rear] = len[now] + 1;
res[rear] = nres;
pre[rear] = now;
val[rear] = num[i];
rear++;
}
}
}
if(ans == 0) puts("0");
else {
print_path(ans);
putchar('\n');
}
}
return 0;
}

浙公网安备 33010602011771号