题意:给你一个数N,以及m个小于10的十进制数字,要你找到N的一个最小正整数倍的数,它的每位数字都是由这m个数字中的数字组成。
思路:bfs+剪枝。需要从高位向低位拓展,其实也就是按照我们手算的过程。这里有一个很重要的剪枝,如果得到了一个之前得到过的余数,那么是没有必要再进入队列的,因为它只要输出最小的正整数倍数。这样有了剪枝就使得队列有为空的可能,如果最后为空都没有找到答案自然输出0。由于答案可能非常大,所以开一个数组存bfs的每个状态,也可以用字符串(但据说用字符串在POJ上会超时),最后递归打印输出。
注意一点是如果N为0那么直接输出0就行了。
思路是参考了网上的题解。很多人都说用stl会超时,当然这不是真的。
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define MAXN 5005
using namespace std;
struct Node
{
int use,data,pre,id;
Node(int a=0,int b=0,int c=0,int d=0):data(a),pre(b),id(c),use(d) {}
};
bool vis[MAXN];
Node path[MAXN];
void Print_path(Node p)
{
if(p.pre==-1) return;
Print_path(path[p.pre]);
printf("%d",p.use);
}
int main()
{
int N,M;
while(scanf("%d",&N)!=EOF)
{
scanf("%d",&M);
int num[10];
for(int i=0; i<M; ++i)
scanf("%d",&num[i]);
memset(vis,0,sizeof(vis));
bool ok=false;
int _id=0;
if(N)
{
sort(num,num+M);
queue<Node> q;
Node st(0,-1,_id,0);
path[_id++]=st;
q.push(st);
while(!q.empty()&&!ok)
{
Node tmp=q.front();
q.pop();
for(int i=0; i<M; ++i)
{
int re=tmp.data;
if(!re&&!tmp.id&&!num[i]) continue;
int x=(re*10+num[i])%N;
if(vis[x]) continue;
else vis[x]=true;
Node elem(x,tmp.id,_id,num[i]);
path[_id++]=elem;
if(!x)
{
ok=true;
break;
}
else q.push(elem);
}
}
}
if(!ok) printf("0");
else Print_path(path[_id-1]);
printf("\n");
}
return 0;
}