先贴一发,还不是太理解
/**
* 比较巧的广搜+记录最短路径
* 搜余数,骚的一匹。。。
* 用余数做结点,复杂度10000
* 复习题
* n1 mod k = (n1 mod k) mod k
* (n1 + n2) mod k = ((n1 mod k) + (n2 mod k)) mod k
* (n1 * w) mod k = ((n1 mod k) * w) mod k
* 已保证先搜到的是最小的。
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int mmax = 10002;
bool book[mmax];
bool unincluded[11];
int n;
char route[mmax];//字符串输出,每个下标(余数)只存一位数,也可以用int
int pre[mmax];
bool bfs()
{
queue<int> Q;
Q.push(0);//先放一个数,为何放0
int now;//代表余数,其实本来是要代表的未取余的数,但经过证明可以用余数代替。
while(!Q.empty())
{
now = Q.front();
Q.pop();
for(int i = 0; i < 10; i++)//必须从0开始,遍历数字0-9
{
if(unincluded[i])//不允许使用的数字
continue;
if(now == 0 && i == 0)//排除第一个??
continue;
int next = (now * 10 + i)%n;//下一个余数
if(book[next])//如果余数用过,则不加入,剪枝
continue;
route[next] = '0' + i;
book[next] = true;
pre[next] = now;//记录到达这个余数前面的余数
Q.push(next);
if(next == 0)//可以放到开头
{
return true;
}
}
}
return false;
}
void out()
{
int p = 0;
string output;
while(p != 0 || output.empty())
{
output += route[p];
p = pre[p];
}
reverse(output.begin(), output.end());
puts(output.c_str());//c语言遗留的,书上写的,返回指针
}
int t;
int main()
{
int m;
t = 1;
while(scanf("%d%d", &n, &m) != EOF)
{
memset(unincluded, 0, sizeof(unincluded));
memset(book, 0, sizeof(book));
int num;
for(int i = 1; i <= m; i++)
{
scanf("%d", &num);
unincluded[num] = true;
}
printf("Case %d: ", t);
if(bfs())
{
out();
}
else
{
printf("-1\n");
}
t++;
}
return 0;
}