hdu 4474 转化为bfs + 一个巧妙的剪枝~
比赛的时候只想到的暴力枚举的方法 枚举n的倍数 但是不确定到哪里为止输出-1。看了题解其实可以转化为, 0-9这十个数字里面的若干个数字组合出一个数,使这个数是N的倍数,求最小的这个这样的数,不存在的话输出-1。这样地话就成了一道bfs的题目,再加一个很巧妙的剪枝,可以在规定时间求出。
参考大神博客:http://blog.csdn.net/yang_7_46/article/details/12356587
优化方法:如果一个数%N==0,那么这个数就是N的倍数。在没有找到的前提下,如果A%N==B%N,而且A<B,那么其实我们就可以取A而不取B,因为如果在A末尾增加C可以使得AC%N==0,那么BC%N也等于0,易得:如果A和B追加数之后%N==0,那么最优条件下追加的数肯定相同。
参考大神代码: http://www.cnblogs.com/wally/archive/2013/03/24/2978645.html
1 #include<iostream> 2 #include<cstring> 3 #include<queue> 4 const int N=10010; 5 using namespace std; 6 int n,m; 7 int a[10]; 8 int pre[N],num[N]; 9 10 void print(int u) 11 { 12 if(pre[u]!=-1)print(pre[u]);//pre[]保存的是形成u的前一个结点,直到为-1; 13 printf("%d",num[u]);//由于num[]保存的记录u的最后一个数字,应此应该逆序输出 14 } 15 16 void bfs() 17 { 18 queue<int>Q; 19 for(int i=1; i<=9; i++) 20 if(!a[i]) 21 { 22 int t=i%n; 23 if(t==0) 24 { 25 printf("%d",i); 26 return ; 27 } 28 Q.push(t); 29 num[t]=i; 30 } 31 while(!Q.empty()) 32 { 33 int u=Q.front(); 34 Q.pop(); 35 for(int i=0; i<=9; i++)if(!a[i]) 36 { 37 int t=(u*10+i)%n; 38 if(num[t]==-1) 39 { 40 Q.push(t);//只存余数t 41 pre[t]=u;//由于记录到达t的前一个结点u; 42 num[t]=i;//记录形成t的最后一位数字 43 } 44 if(t==0) 45 { 46 print(t); 47 return ; 48 } 49 } 50 } 51 printf("-1"); 52 } 53 54 55 int main() 56 { 57 int _case=1; 58 while(~scanf("%d%d",&n,&m)) 59 { 60 memset(a,0,sizeof(a)); 61 memset(pre,-1,sizeof(pre)); 62 memset(num,-1,sizeof(num)); 63 int x; 64 while(m--) 65 { 66 scanf("%d",&x); 67 a[x]=1; 68 } 69 printf("Case %d: ",_case++); 70 bfs(); 71 printf("\n"); 72 } 73 return 0; 74 }