题意:n和m,m个十进制的单位数字(0-9),求最小的数ans,使ans是n的倍数(除0),且ans中不包括输入的十进制数字。不存在输出-1。
使用BFS搜索,从小向大枚举可以保证构造出来的数是递增的,若不加判断直接搜索的话,复杂度非常高。如果一个数%N==0,这个数就是N的倍数。在没有找到的时候,若A%N==B%N,且A<B,那么其实可以取A而不取B,因为如果在A末尾增加C可以使得AC%N==0,那么BC%N也等于0,可知如果A和B追加数之后%N==0,最优条件下追加的数肯定相同。因此只需维护组合出来的数%N的值即可,如果在搜索的途中出现了相同的%N值,就可以忽略了,肯定没有前面的更好。
#include<iostream>
#include<queue>
using namespace std;
#define N 10010
int p[N]; //pre[v]记录到达v的前一节点u
int num[N]; //num[v]记录形成v的最后一位数字
bool a[10]; //被除去的数据
int n;
void Init()
{
memset(p,-1,sizeof(p));
memset(num,-1,sizeof(num));
memset(a,false,sizeof(a));
}
void Show(int u) //递归打印结果
{
if(p[u]!=-1)
Show(p[u]);
printf("%d",num[u]);
}
void bfs()
{
int i,t,u;
queue<int> q;
for(i=1;i<10;i++) //注意0不算,要除去
if(!a[i])
{
t=i%n;
if(t==0) //结果只有一位数字的情况
{
printf("%d",i);
return ;
}
q.push(t);
num[t]=i;
}
while(!q.empty())
{
u=q.front();
q.pop();
for(i=0;i<10;i++)
if(!a[i])
{
t=(10*u+i)%n;
if(num[t]==-1) //之前未出现过
{
q.push(t);
p[t]=u;
num[t]=i;
}
if(t==0)
{
Show(t);
return ;
}
}
}
printf("-1");
}
int main()
{
int k=0,m,x;
while(scanf("%d%d",&n,&m)==2)
{
Init();
while(m--)
{
scanf("%d",&x);
a[x]=true;
}
printf("Case %d: ",++k);
bfs();
putchar('\n');
}
return 0;
}
HDU ACM 4474 Yet Another Multiple Problem->数论(数位BFS)
原文地址:http://blog.csdn.net/a809146548/article/details/46425589