题意: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