题意:求给定数n的最小的倍数,使其中不包含给出的m个十进制数。
状态太多了。。。参看别人的思路,
就是在每一位上对可以出现的数进行枚举,然后bfs。。。直到出现第一个节点中m==0,就输出。
每个节点记录三个值
c:末尾的那个数字
m:这个节点所代表的数字对n取模的值
f:父节点
对于一个节点,如果在其后面加一个数字i,那么新的m值=(m*10 + i)%n
显然,如果答案存在,那么我们第一个找到的m==0的节点就是答案,然后再用一个递归逆序输出就好。
可以发现,新节点的m的值只与父节点的m值有关,所以,对于相同的m,只有第一个出现m的节点是有用的。
参考来源:点击打开链接
第一次写“这样”的bfs。。。
在l 和 r间移动。。。。长见识。。。长思维。。。click zan~
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
struct node
{
char c;
int m,f;
}d[10010],tmp;
bool h[10010],g[10];
void out(int a)
{
if(a==-1) return;
out(d[a].f);
putchar(d[a].c);
}
int main()
{
int cas=0,n,m,l,r;
while(scanf("%d%d",&n,&m)!=EOF)
{
printf("Case %d: ",++cas);
memset(g,false,sizeof(g));
memset(h,false,sizeof(h));
int ans = -1;
for(int i=0;i<m;i++)
{
int x;
scanf("%d",&x);
g[x]=true;
}
l=r=0;
for(int i=1;i<10;i++)
{
if(g[i]==false)
{
tmp.c = i+'0';
h[tmp.m=i%n] = true;
tmp.f = -1;
d[r++]=tmp;
if(tmp.m==0)
{
ans = r-1;
break;
}
}
}
while(l<r && ans == -1)
{
for(int i=0;i<10;i++)
{
if(g[i]==false)
{
tmp.c = i+'0';
tmp.m = (d[l].m*10+i)%n;
if(h[tmp.m]==false)
{
h[tmp.m]=true;
tmp.f = l;
d[r++]=tmp;
if(tmp.m == 0)
{
ans = r-1;
break;
}
}
}
}
l++;
}
if(ans==-1) puts("-1");
else
{
out(ans);
putchar('\n');
}
}
return 0;
}