题目大意:给出一个数n,求n以及倍数里,不存在给出的m个[0,9]的数的最小数是多少?
解题思路:最近都不知怎么了,各种烦心事,各种不顺心,做题找不到感觉,感觉东西太多,又想抓住全部却什么也抓不到。就连自己最熟悉的搜索,居然都写不出来了,自己到底怎么了!唉......这个题直接暴力会超时的,虽然数只有1e4,但是倍数最终到达多少都不确定的,所以用进行搜索+剪枝处理。用一个数组标记不能出现的数字,用一个数组来保存答案的每一位,一个数组来存答案的前缀用来递归打印。然后就bfs遍历即可,详见code。
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4474
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 1e4+100;
int n,m,d,cas;
int num[MAXN],pre[MAXN],tmp[10];
void print(int x){ //打印答案
if(pre[x]!=-1) print(pre[x]); //不是首位则进行递归
printf("%d",num[x]); //否则进行输出
}
void bfs(){
queue<int> q;
for(int i=1;i<=9;++i) if(!tmp[i]){ //一位数判断
int s=i%n;
if(!s){
printf("%d",i);
return ;
}
q.push(s);
num[s]=i; //记录最高位
}
while(!q.empty()){
int s=q.front();
q.pop();
for(int i=0;i<=9;++i) if(!tmp[i]){ //每一位进行搜索构造
int t=(s*10+i)%n; //从最高位开始
if(num[t]==-1){ //如果未访问则记录加入队列
q.push(t);
pre[t]=s; //记录数值的前缀,用于输出
num[t]=i; //记录每一位答案
}
if(!t){ //当搜索到,则递归打印
print(t);
return ;
}
}
}
printf("-1");
}
int main(){
//freopen("input.txt","r",stdin);
cas=0;
while(~scanf("%d%d",&n,&m)){
memset(pre,-1,sizeof(pre));
memset(num,-1,sizeof(num));
memset(tmp,0,sizeof(tmp));
for(int i=0;i<m;++i){ //接收数值,进行标记
scanf("%d",&d);
tmp[d]=1;
}
printf("Case %d: ",++cas);
bfs();
printf("\n");
}
return 0;
}